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 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
270 g_return_val_if_fail (uri, FALSE);
272 result = hildon_uri_open (uri, action, &err);
274 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
275 uri, action, err && err->message ? err->message : "unknown error");
285 modest_platform_activate_uri (const gchar *uri)
287 HildonURIAction *action;
288 gboolean result = FALSE;
289 GSList *actions, *iter = NULL;
291 g_return_val_if_fail (uri, FALSE);
295 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
297 for (iter = actions; iter; iter = g_slist_next (iter)) {
298 action = (HildonURIAction*) iter->data;
299 if (action && strcmp (hildon_uri_action_get_service (action),
300 "com.nokia.modest") == 0) {
301 result = checked_hildon_uri_open (uri, action);
306 /* if we could not open it with email, try something else */
308 result = checked_hildon_uri_open (uri, NULL);
311 ModestWindow *parent =
312 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
313 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
314 _("mcen_ib_unsupported_link"));
321 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
325 gchar *uri_path = NULL;
327 uri_path = g_strconcat ("file://", path, NULL);
328 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
331 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
333 result = hildon_mime_open_file (con, uri_path);
335 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
343 } ModestPlatformPopupInfo;
346 delete_uri_popup (GtkWidget *menu,
350 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
352 g_free (popup_info->uri);
353 hildon_uri_free_actions (popup_info->actions);
359 activate_uri_popup_item (GtkMenuItem *menu_item,
363 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
364 const gchar* action_name;
366 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
368 g_printerr ("modest: no action name defined\n");
372 /* special handling for the copy menu item -- copy the uri to the clipboard */
373 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
374 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
375 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
376 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
378 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
379 action_name += strlen ("mailto:");
381 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
382 return; /* we're done */
385 /* now, the real uri-actions... */
386 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
387 HildonURIAction *action = (HildonURIAction *) node->data;
388 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
389 if (!checked_hildon_uri_open (popup_info->uri, action)) {
390 ModestWindow *parent =
391 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
392 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
393 _("mcen_ib_unsupported_link"));
401 modest_platform_show_uri_popup (const gchar *uri)
403 GSList *actions_list;
408 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
409 if (actions_list != NULL) {
411 GtkWidget *menu = gtk_menu_new ();
412 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
414 popup_info->actions = actions_list;
415 popup_info->uri = g_strdup (uri);
417 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
418 GtkWidget *menu_item;
419 const gchar *action_name;
420 const gchar *translation_domain;
421 HildonURIAction *action = (HildonURIAction *) node->data;
422 action_name = hildon_uri_action_get_name (action);
423 translation_domain = hildon_uri_action_get_translation_domain (action);
424 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
425 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
426 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
429 if (hildon_uri_is_default_action (action, NULL)) {
430 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
432 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
434 gtk_widget_show (menu_item);
437 /* always add the copy item */
438 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
439 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
440 g_strconcat (URI_ACTION_COPY, uri, NULL),
442 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
443 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
444 gtk_widget_show (menu_item);
447 /* and what to do when the link is deleted */
448 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
449 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
452 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
460 modest_platform_get_icon (const gchar *name)
463 GdkPixbuf* pixbuf = NULL;
464 GtkIconTheme *current_theme = NULL;
466 g_return_val_if_fail (name, NULL);
468 /* strlen == 0 is not really an error; it just
469 * means the icon is not available
471 if (!name || strlen(name) == 0)
474 #if 0 /* do we still need this? */
475 if (g_str_has_suffix (name, ".png")) { /*FIXME: hack*/
476 pixbuf = gdk_pixbuf_new_from_file (name, &err);
478 g_printerr ("modest: error loading icon '%s': %s\n",
486 current_theme = gtk_icon_theme_get_default ();
487 pixbuf = gtk_icon_theme_load_icon (current_theme, name, 26,
488 GTK_ICON_LOOKUP_NO_SVG,
491 g_printerr ("modest: error loading theme icon '%s': %s\n",
499 modest_platform_get_app_name (void)
501 return _("mcen_ap_name");
505 entry_insert_text (GtkEditable *editable,
514 chars = gtk_editable_get_chars (editable, 0, -1);
515 chars_length = g_utf8_strlen (chars, -1);
517 /* Show WID-INF036 */
518 if (chars_length >= 20) {
519 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
520 _CS("ckdg_ib_maximum_characters_reached"));
522 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
526 tmp = g_strndup (folder_name_forbidden_chars,
527 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
528 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
529 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
534 /* Write the text in the entry if it's valid */
535 g_signal_handlers_block_by_func (editable,
536 (gpointer) entry_insert_text, data);
537 gtk_editable_insert_text (editable, text, length, position);
538 g_signal_handlers_unblock_by_func (editable,
539 (gpointer) entry_insert_text, data);
542 /* Do not allow further processing */
543 g_signal_stop_emission_by_name (editable, "insert_text");
547 entry_changed (GtkEditable *editable,
551 GtkWidget *ok_button;
554 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
555 ok_button = GTK_WIDGET (buttons->next->data);
557 chars = gtk_editable_get_chars (editable, 0, -1);
558 g_return_if_fail (chars != NULL);
561 if (g_utf8_strlen (chars,-1) >= 21)
562 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
563 _CS("ckdg_ib_maximum_characters_reached"));
565 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
568 g_list_free (buttons);
573 launch_sort_headers_dialog (GtkWindow *parent_window,
574 HildonSortDialog *dialog)
576 ModestHeaderView *header_view = NULL;
578 GtkSortType sort_type;
580 gint default_key = 0;
582 gboolean outgoing = FALSE;
583 gint current_sort_colid = -1;
584 GtkSortType current_sort_type;
585 gint attachments_sort_id;
586 gint priority_sort_id;
587 GtkTreeSortable *sortable;
589 /* Get header window */
590 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
591 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
592 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
597 /* Add sorting keys */
598 cols = modest_header_view_get_columns (header_view);
599 if (cols == NULL) return;
600 int sort_model_ids[6];
604 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
605 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
607 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
609 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
610 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
612 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
613 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
616 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
618 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
619 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
621 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
622 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
624 default_key = sort_key;
626 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
627 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
629 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
631 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
633 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
634 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
635 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
636 attachments_sort_id = sort_key;
638 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_size"));
639 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
640 sort_ids[sort_key] = 0;
642 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
643 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
644 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
645 priority_sort_id = sort_key;
647 sortable = GTK_TREE_SORTABLE (gtk_tree_model_filter_get_model
648 (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)))));
650 if (!gtk_tree_sortable_get_sort_column_id (sortable,
651 ¤t_sort_colid, ¤t_sort_type)) {
652 hildon_sort_dialog_set_sort_key (dialog, default_key);
653 hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
655 hildon_sort_dialog_set_sort_order (dialog, current_sort_type);
656 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
657 gpointer flags_sort_type_pointer;
658 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
659 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
660 hildon_sort_dialog_set_sort_key (dialog, priority_sort_id);
662 hildon_sort_dialog_set_sort_key (dialog, attachments_sort_id);
664 gint current_sort_keyid = 0;
665 while (current_sort_keyid < 6) {
666 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
669 current_sort_keyid++;
671 hildon_sort_dialog_set_sort_key (dialog, current_sort_keyid);
675 result = gtk_dialog_run (GTK_DIALOG (dialog));
676 if (result == GTK_RESPONSE_OK) {
677 sort_key = hildon_sort_dialog_get_sort_key (dialog);
678 sort_type = hildon_sort_dialog_get_sort_order (dialog);
679 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
680 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
681 GINT_TO_POINTER (sort_ids[sort_key]));
682 /* This is a hack to make it resort rows always when flag fields are
683 * selected. If we do not do this, changing sort field from priority to
684 * attachments does not work */
685 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
687 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
688 sort_model_ids[sort_key]);
691 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
692 gtk_tree_sortable_sort_column_changed (sortable);
695 modest_widget_memory_save (modest_runtime_get_conf (),
696 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
698 /* while (gtk_events_pending ()) */
699 /* gtk_main_iteration (); */
708 on_response (GtkDialog *dialog,
712 GList *child_vbox, *child_hbox;
713 GtkWidget *hbox, *entry;
714 TnyFolderStore *parent;
716 if (response != GTK_RESPONSE_ACCEPT)
720 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
721 hbox = child_vbox->data;
722 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
723 entry = child_hbox->next->data;
725 parent = TNY_FOLDER_STORE (user_data);
727 /* Look for another folder with the same name */
728 if (modest_tny_folder_has_subfolder_with_name (parent,
729 gtk_entry_get_text (GTK_ENTRY (entry)))) {
731 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
732 NULL, _CS("ckdg_ib_folder_already_exists"));
733 /* Select the text */
734 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
735 gtk_widget_grab_focus (entry);
736 /* Do not close the dialog */
737 g_signal_stop_emission_by_name (dialog, "response");
744 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
745 TnyFolderStore *parent,
746 const gchar *dialog_title,
747 const gchar *label_text,
748 const gchar *suggested_name,
751 GtkWidget *accept_btn = NULL;
752 GtkWidget *dialog, *entry, *label, *hbox;
753 GList *buttons = NULL;
756 /* Ask the user for the folder name */
757 dialog = gtk_dialog_new_with_buttons (dialog_title,
759 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
760 _("mcen_bd_dialog_ok"),
762 _("mcen_bd_dialog_cancel"),
766 /* Add accept button (with unsensitive handler) */
767 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
768 accept_btn = GTK_WIDGET (buttons->next->data);
769 /* Create label and entry */
770 label = gtk_label_new (label_text);
771 /* TODO: check that the suggested name does not exist */
772 /* We set 21 as maximum because we want to show WID-INF036
773 when the user inputs more that 20 */
774 entry = gtk_entry_new_with_max_length (21);
776 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
778 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
779 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
781 /* Connect to the response method to avoid closing the dialog
782 when an invalid name is selected*/
783 g_signal_connect (dialog,
785 G_CALLBACK (on_response),
788 /* Track entry changes */
789 g_signal_connect (entry,
791 G_CALLBACK (entry_insert_text),
793 g_signal_connect (entry,
795 G_CALLBACK (entry_changed),
798 /* Create the hbox */
799 hbox = gtk_hbox_new (FALSE, 12);
800 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
801 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
803 /* Add hbox to dialog */
804 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
805 hbox, FALSE, FALSE, 0);
807 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
808 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
810 result = gtk_dialog_run (GTK_DIALOG(dialog));
811 if (result == GTK_RESPONSE_ACCEPT)
812 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
814 gtk_widget_destroy (dialog);
816 while (gtk_events_pending ())
817 gtk_main_iteration ();
823 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
824 TnyFolderStore *parent_folder,
825 gchar *suggested_name,
828 gchar *real_suggested_name = NULL;
831 if(suggested_name == NULL)
833 const gchar *default_name = _("mcen_ia_default_folder_name");
837 for(i = 0; i < 100; ++ i) {
838 gboolean exists = FALSE;
840 sprintf(num_str, "%.2u", i);
843 real_suggested_name = g_strdup (default_name);
845 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
848 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
849 real_suggested_name);
854 g_free (real_suggested_name);
857 /* Didn't find a free number */
859 real_suggested_name = g_strdup (default_name);
861 real_suggested_name = suggested_name;
864 result = modest_platform_run_folder_name_dialog (parent_window,
866 _("mcen_ti_new_folder"),
867 _("mcen_fi_new_folder_name"),
870 if (suggested_name == NULL)
871 g_free(real_suggested_name);
877 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
878 TnyFolderStore *parent_folder,
879 const gchar *suggested_name,
882 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
884 return modest_platform_run_folder_name_dialog (parent_window,
886 _HL("ckdg_ti_rename_folder"),
887 _HL("ckdg_fi_rename_name"),
895 on_destroy_dialog (GtkDialog *dialog)
897 gtk_widget_destroy (GTK_WIDGET(dialog));
898 if (gtk_events_pending ())
899 gtk_main_iteration ();
903 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
904 const gchar *message)
909 dialog = hildon_note_new_confirmation (parent_window, message);
910 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
911 GTK_WINDOW (dialog));
913 response = gtk_dialog_run (GTK_DIALOG (dialog));
915 on_destroy_dialog (GTK_DIALOG(dialog));
917 while (gtk_events_pending ())
918 gtk_main_iteration ();
924 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
925 const gchar *message)
930 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
931 _("mcen_bd_yes"), GTK_RESPONSE_YES,
932 _("mcen_bd_no"), GTK_RESPONSE_NO,
934 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
935 response = gtk_dialog_run (GTK_DIALOG (dialog));
937 on_destroy_dialog (GTK_DIALOG(dialog));
939 while (gtk_events_pending ())
940 gtk_main_iteration ();
948 modest_platform_run_information_dialog (GtkWindow *parent_window,
949 const gchar *message)
953 note = hildon_note_new_information (parent_window, message);
954 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
957 g_signal_connect_swapped (note,
959 G_CALLBACK (on_destroy_dialog),
962 gtk_widget_show_all (note);
967 typedef struct _ConnectAndWaitData {
969 GMainLoop *wait_loop;
970 gboolean has_callback;
972 } ConnectAndWaitData;
976 quit_wait_loop (TnyAccount *account,
977 ConnectAndWaitData *data)
979 /* Set the has_callback to TRUE (means that the callback was
980 executed and wake up every code waiting for cond to be
982 g_mutex_lock (data->mutex);
983 data->has_callback = TRUE;
985 g_main_loop_quit (data->wait_loop);
986 g_mutex_unlock (data->mutex);
990 on_connection_status_changed (TnyAccount *account,
991 TnyConnectionStatus status,
994 TnyConnectionStatus conn_status;
995 ConnectAndWaitData *data;
997 /* Ignore if reconnecting or disconnected */
998 conn_status = tny_account_get_connection_status (account);
999 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1000 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1003 /* Remove the handler */
1004 data = (ConnectAndWaitData *) user_data;
1005 g_signal_handler_disconnect (account, data->handler);
1007 /* Quit from wait loop */
1008 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1012 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1017 /* Quit from wait loop */
1018 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1022 modest_platform_connect_and_wait (GtkWindow *parent_window,
1023 TnyAccount *account)
1025 ConnectAndWaitData *data = NULL;
1026 gboolean device_online;
1028 TnyConnectionStatus conn_status;
1030 device = modest_runtime_get_device();
1031 device_online = tny_device_is_online (device);
1033 /* If there is no account check only the device status */
1038 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1041 /* Return if the account is already connected */
1042 conn_status = tny_account_get_connection_status (account);
1043 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1046 /* Create the helper */
1047 data = g_slice_new0 (ConnectAndWaitData);
1048 data->mutex = g_mutex_new ();
1049 data->has_callback = FALSE;
1051 /* Connect the device */
1052 if (!device_online) {
1053 /* Track account connection status changes */
1054 data->handler = g_signal_connect (account, "connection-status-changed",
1055 G_CALLBACK (on_connection_status_changed),
1057 /* Try to connect the device */
1058 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1060 /* If the device connection failed then exit */
1061 if (!device_online && data->handler)
1064 /* Force a reconnection of the account */
1065 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1066 on_tny_camel_account_set_online_cb, data);
1069 /* Wait until the callback is executed */
1070 g_mutex_lock (data->mutex);
1071 if (!data->has_callback) {
1072 data->wait_loop = g_main_loop_new (NULL, FALSE);
1073 gdk_threads_leave ();
1074 g_mutex_unlock (data->mutex);
1075 g_main_loop_run (data->wait_loop);
1076 g_mutex_lock (data->mutex);
1077 gdk_threads_enter ();
1079 g_mutex_unlock (data->mutex);
1083 if (g_signal_handler_is_connected (account, data->handler))
1084 g_signal_handler_disconnect (account, data->handler);
1085 g_mutex_free (data->mutex);
1086 g_main_loop_unref (data->wait_loop);
1087 g_slice_free (ConnectAndWaitData, data);
1090 conn_status = tny_account_get_connection_status (account);
1091 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1095 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1097 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1098 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1099 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1100 /* This must be a maildir account, which does not require a connection: */
1105 return modest_platform_connect_and_wait (parent_window, account);
1109 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1112 return TRUE; /* Maybe it is something local. */
1114 gboolean result = TRUE;
1115 if (TNY_IS_FOLDER (folder_store)) {
1116 /* Get the folder's parent account: */
1117 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1118 if (account != NULL) {
1119 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1120 g_object_unref (account);
1122 } else if (TNY_IS_ACCOUNT (folder_store)) {
1123 /* Use the folder store as an account: */
1124 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1131 modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1133 TnyAccount *account = NULL;
1134 gboolean result = TRUE;
1136 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1138 if (TNY_IS_FOLDER (folder_store)) {
1139 /* Get the folder's parent account: */
1140 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1141 } else if (TNY_IS_ACCOUNT (folder_store)) {
1142 account = TNY_ACCOUNT(folder_store);
1143 g_object_ref(account);
1146 if (account != NULL) {
1147 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1148 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1149 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1150 /* This must be a maildir account, which does
1151 * not require a connection: */
1155 g_object_unref (account);
1164 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1165 ModestSortDialogType type)
1167 GtkWidget *dialog = NULL;
1170 dialog = hildon_sort_dialog_new (parent_window);
1171 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1172 GTK_WINDOW (dialog));
1174 hildon_help_dialog_help_enable (GTK_DIALOG(dialog),
1175 "applications_email_sort",
1176 modest_maemo_utils_get_osso_context());
1178 /* Fill sort keys */
1180 case MODEST_SORT_HEADERS:
1181 launch_sort_headers_dialog (parent_window,
1182 HILDON_SORT_DIALOG(dialog));
1187 on_destroy_dialog (GTK_DIALOG(dialog));
1192 modest_platform_set_update_interval (guint minutes)
1194 #ifdef MODEST_HAVE_LIBALARM
1196 ModestConf *conf = modest_runtime_get_conf ();
1200 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1202 /* Delete any existing alarm,
1203 * because we will replace it: */
1205 /* TODO: What does the alarm_event_del() return value mean? */
1206 alarm_event_del(alarm_cookie);
1208 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1211 /* 0 means no updates: */
1216 /* Register alarm: */
1218 /* Set the interval in alarm_event_t structure: */
1219 alarm_event_t *event = g_new0(alarm_event_t, 1);
1220 event->alarm_time = minutes * 60; /* seconds */
1222 /* Set recurrence every few minutes: */
1223 event->recurrence = minutes;
1224 event->recurrence_count = -1; /* Means infinite */
1226 /* Specify what should happen when the alarm happens:
1227 * It should call this D-Bus method: */
1229 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1230 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1231 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1232 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1234 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1235 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1236 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1237 * This is why we want to use the Alarm API instead of just g_timeout_add().
1238 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1240 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1242 alarm_cookie = alarm_event_add (event);
1245 alarm_event_free (event);
1247 /* Store the alarm ID in GConf, so we can remove it later:
1248 * This is apparently valid between application instances. */
1249 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1251 if (!alarm_cookie) {
1253 const alarm_error_t alarm_error = alarmd_get_error ();
1254 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1256 /* Give people some clue: */
1257 /* The alarm API should have a function for this: */
1258 if (alarm_error == ALARMD_ERROR_DBUS) {
1259 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1260 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1261 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1262 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1263 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1264 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1265 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1266 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1267 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1268 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1269 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1274 #endif /* MODEST_HAVE_LIBALARM */
1279 modest_platform_on_new_headers_received (TnyList *header_list)
1281 #ifdef MODEST_HAVE_HILDON_NOTIFY
1282 HildonNotification *notification;
1284 GSList *notifications_list = NULL;
1286 /* Get previous notifications ids */
1287 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1288 MODEST_CONF_NOTIFICATION_IDS,
1289 MODEST_CONF_VALUE_INT, NULL);
1291 iter = tny_list_create_iterator (header_list);
1292 while (!tny_iterator_is_done (iter)) {
1293 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1294 const gchar *display_date;
1295 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1296 TnyFolder *folder = tny_header_get_folder (header);
1297 gboolean first_notification = TRUE;
1300 /* constant string, don't free */
1301 display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header));
1303 display_address = g_strdup(tny_header_get_from (header));
1304 modest_text_utils_get_display_address (display_address); /* string is changed in-place */
1306 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1307 notification = hildon_notification_new (summary,
1308 tny_header_get_subject (header),
1309 "qgn_list_messagin",
1311 /* Create the message URL */
1312 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1313 tny_header_get_uid (header));
1315 hildon_notification_add_dbus_action(notification,
1318 MODEST_DBUS_SERVICE,
1321 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1325 /* Play sound if the user wants. Show the LED
1326 pattern. Show and play just one */
1327 if (G_UNLIKELY (first_notification)) {
1328 first_notification = FALSE;
1329 if (modest_conf_get_bool (modest_runtime_get_conf (),
1330 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1332 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1333 "sound-file", "/usr/share/sounds/ui-new_email.wav");
1336 /* Set the led pattern */
1337 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1339 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1341 "PatternCommunicationEmail");
1344 /* Notify. We need to do this in an idle because this function
1345 could be called from a thread */
1346 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1348 /* Save id in the list */
1349 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1350 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1351 /* We don't listen for the "closed" signal, because we
1352 don't care about if the notification was removed or
1353 not to store the list in gconf */
1355 /* Free & carry on */
1356 g_free (display_address);
1359 g_object_unref (folder);
1360 g_object_unref (header);
1361 tny_iterator_next (iter);
1363 g_object_unref (iter);
1366 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1367 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1369 g_slist_free (notifications_list);
1371 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1375 modest_platform_remove_new_mail_notifications (void)
1377 #ifdef MODEST_HAVE_HILDON_NOTIFY
1378 GSList *notif_list = NULL;
1380 /* Get previous notifications ids */
1381 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1382 MODEST_CONF_NOTIFICATION_IDS,
1383 MODEST_CONF_VALUE_INT, NULL);
1385 while (notif_list) {
1387 NotifyNotification *notif;
1389 /* Nasty HACK to remove the notifications, set the id
1390 of the existing ones and then close them */
1391 notif_id = GPOINTER_TO_INT(notif_list->data);
1392 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1393 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1395 /* Close the notification, note that some ids could be
1396 already invalid, but we don't care because it does
1398 notify_notification_close(notif, NULL);
1399 g_object_unref(notif);
1401 /* Delete the link, it's like going to the next */
1402 notif_list = g_slist_delete_link (notif_list, notif_list);
1406 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1407 notif_list, MODEST_CONF_VALUE_INT, NULL);
1409 g_slist_free (notif_list);
1411 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1417 modest_platform_get_global_settings_dialog ()
1419 return modest_maemo_global_settings_dialog_new ();
1423 modest_platform_show_help (GtkWindow *parent_window,
1424 const gchar *help_id)
1426 osso_return_t result;
1427 g_return_if_fail (help_id);
1429 result = hildon_help_show (modest_maemo_utils_get_osso_context(),
1430 help_id, HILDON_HELP_SHOW_DIALOG);
1432 if (result != OSSO_OK) {
1434 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1435 hildon_banner_show_information (GTK_WIDGET (parent_window),
1443 modest_platform_show_search_messages (GtkWindow *parent_window)
1445 osso_return_t result = OSSO_ERROR;
1447 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1448 "osso_global_search",
1449 "search_email", NULL, DBUS_TYPE_INVALID);
1451 if (result != OSSO_OK) {
1452 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1457 modest_platform_show_addressbook (GtkWindow *parent_window)
1459 osso_return_t result = OSSO_ERROR;
1461 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1463 "top_application", NULL, DBUS_TYPE_INVALID);
1465 if (result != OSSO_OK) {
1466 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1471 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1473 GtkWidget *widget = modest_folder_view_new (query);
1475 /* Show one account by default */
1476 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1477 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1480 /* Restore settings */
1481 modest_widget_memory_restore (modest_runtime_get_conf(),
1483 MODEST_CONF_FOLDER_VIEW_KEY);
1489 modest_platform_information_banner (GtkWidget *parent,
1490 const gchar *icon_name,
1493 hildon_banner_show_information (parent, icon_name, text);
1497 modest_platform_animation_banner (GtkWidget *parent,
1498 const gchar *animation_name,
1501 GtkWidget *inf_note = NULL;
1503 g_return_val_if_fail (text != NULL, NULL);
1505 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1513 TnyAccount *account;
1516 } CheckAccountIdleData;
1518 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1521 on_timeout_check_account_is_online(gpointer user_data)
1523 printf ("DEBUG: %s:\n", __FUNCTION__);
1524 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1526 g_return_val_if_fail (data && data->account, FALSE);
1528 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1529 tny_account_get_connection_status (data->account));
1531 gboolean stop_trying = FALSE;
1532 if (data && data->account &&
1533 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1534 * after which the account is likely to be usable, or never likely to be usable soon: */
1535 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1537 data->is_online = TRUE;
1542 /* Give up if we have tried too many times: */
1543 if (data->count_tries >= NUMBER_OF_TRIES)
1548 /* Wait for another timeout: */
1549 ++(data->count_tries);
1554 /* Allow the function that requested this idle callback to continue: */
1556 g_main_loop_quit (data->loop);
1559 g_object_unref (data->account);
1561 return FALSE; /* Don't call this again. */
1563 return TRUE; /* Call this timeout callback again. */
1567 /* Return TRUE immediately if the account is already online,
1568 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1569 * soon as the account is online, or FALSE if the account does
1570 * not become online in the NUMBER_OF_TRIES seconds.
1571 * This is useful when the D-Bus method was run immediately after
1572 * the application was started (when using D-Bus activation),
1573 * because the account usually takes a short time to go online.
1574 * The return value is maybe not very useful.
1577 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1579 g_return_val_if_fail (account, FALSE);
1581 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1583 if (!tny_device_is_online (modest_runtime_get_device())) {
1584 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1588 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1589 * so we avoid wait unnecessarily: */
1590 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1591 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1595 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1596 __FUNCTION__, tny_account_get_connection_status (account));
1598 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1599 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1600 * we want to avoid. */
1601 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1604 /* This blocks on the result: */
1605 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1606 data->is_online = FALSE;
1607 data->account = account;
1608 g_object_ref (data->account);
1609 data->count_tries = 0;
1611 GMainContext *context = NULL; /* g_main_context_new (); */
1612 data->loop = g_main_loop_new (context, FALSE /* not running */);
1614 g_timeout_add (1000, on_timeout_check_account_is_online, data);
1616 /* This main loop will run until the idle handler has stopped it: */
1617 g_main_loop_run (data->loop);
1619 g_main_loop_unref (data->loop);
1620 /* g_main_context_unref (context); */
1622 g_slice_free (CheckAccountIdleData, data);
1624 return data->is_online;
1630 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1632 /* GTK_RESPONSE_HELP means we need to show the certificate */
1633 if (response_id == GTK_RESPONSE_HELP) {
1637 /* Do not close the dialog */
1638 g_signal_stop_emission_by_name (dialog, "response");
1640 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1641 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1642 gtk_dialog_run (GTK_DIALOG(note));
1643 gtk_widget_destroy (note);
1649 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1650 const gchar *certificate)
1654 ModestWindow *main_win;
1656 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1657 g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
1662 /* don't create it */
1663 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
1664 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1667 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1670 note = hildon_note_new_confirmation_add_buttons (
1671 GTK_WINDOW(main_win),
1673 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1674 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1675 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1678 g_signal_connect (G_OBJECT(note), "response",
1679 G_CALLBACK(on_cert_dialog_response),
1680 (gpointer) certificate);
1682 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1684 response = gtk_dialog_run(GTK_DIALOG(note));
1686 on_destroy_dialog (GTK_DIALOG(note));
1689 return response == GTK_RESPONSE_OK;
1695 modest_platform_run_alert_dialog (const gchar* prompt,
1696 gboolean is_question)
1698 ModestWindow *main_win;
1700 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1701 g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
1702 " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
1703 return is_question ? FALSE : TRUE;
1706 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1707 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1709 gboolean retval = TRUE;
1711 /* The Tinymail documentation says that we should show Yes and No buttons,
1712 * when it is a question.
1713 * Obviously, we need tinymail to use more specific error codes instead,
1714 * so we know what buttons to show. */
1715 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win),
1717 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1718 GTK_WINDOW (dialog));
1720 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1721 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1723 on_destroy_dialog (GTK_DIALOG(dialog));
1725 /* Just show the error text and use the default response: */
1726 modest_platform_run_information_dialog (GTK_WINDOW (main_win),