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.
32 #endif /*HAVE_CONFIG_H*/
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
37 #include <modest-runtime.h>
38 #include <modest-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-error.h>
50 #include <tny-camel-folder.h>
51 #include <tny-camel-imap-folder.h>
52 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_TOOLKIT_HILDON2
54 #include <modest-accounts-window.h>
55 #include <hildon/hildon-pannable-area.h>
56 #include <hildon/hildon-gtk.h>
57 #include <modest-header-window.h>
58 #include <modest-folder-window.h>
59 #include <modest-maemo-utils.h>
62 #ifdef MODEST_PLATFORM_MAEMO
63 #include "maemo/modest-osso-state-saving.h"
64 #endif /* MODEST_PLATFORM_MAEMO */
65 #ifndef MODEST_TOOLKIT_GTK
66 #include "maemo/modest-hildon-includes.h"
67 #include "maemo/modest-connection-specific-smtp-window.h"
68 #endif /* !MODEST_TOOLKIT_GTK */
69 #include <modest-utils.h>
71 #include "widgets/modest-ui-constants.h"
72 #include <widgets/modest-main-window.h>
73 #include <widgets/modest-msg-view-window.h>
74 #include <widgets/modest-account-view-window.h>
75 #include <widgets/modest-details-dialog.h>
76 #include <widgets/modest-attachments-view.h>
77 #include "widgets/modest-folder-view.h"
78 #include "widgets/modest-global-settings-dialog.h"
79 #include "modest-account-mgr-helpers.h"
80 #include "modest-mail-operation.h"
81 #include "modest-text-utils.h"
82 #include <modest-widget-memory.h>
83 #include <tny-error.h>
84 #include <tny-simple-list.h>
85 #include <tny-msg-view.h>
86 #include <tny-device.h>
87 #include <tny-merge-folder.h>
89 #include <gtkhtml/gtkhtml.h>
91 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
93 typedef struct _GetMsgAsyncHelper {
95 ModestMailOperation *mail_op;
102 typedef enum _ReplyForwardAction {
106 } ReplyForwardAction;
108 typedef struct _ReplyForwardHelper {
109 guint reply_forward_type;
110 ReplyForwardAction action;
113 GtkWidget *parent_window;
115 } ReplyForwardHelper;
117 typedef struct _MoveToHelper {
118 GtkTreeRowReference *reference;
122 typedef struct _PasteAsAttachmentHelper {
123 ModestMsgEditWindow *window;
125 } PasteAsAttachmentHelper;
133 * The do_headers_action uses this kind of functions to perform some
134 * action to each member of a list of headers
136 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
138 static void do_headers_action (ModestWindow *win,
142 static void open_msg_cb (ModestMailOperation *mail_op,
149 static void reply_forward_cb (ModestMailOperation *mail_op,
156 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
158 static void folder_refreshed_cb (ModestMailOperation *mail_op,
162 static void on_send_receive_finished (ModestMailOperation *mail_op,
165 static gint header_list_count_uncached_msgs (TnyList *header_list);
167 static gboolean connect_to_get_msg (ModestWindow *win,
168 gint num_of_uncached_msgs,
169 TnyAccount *account);
171 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
173 static void do_create_folder (GtkWindow *window,
174 TnyFolderStore *parent_folder,
175 const gchar *suggested_name);
177 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
179 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
180 GtkWidget *folder_view,
181 TnyFolderStore *dst_folder,
182 ModestMainWindow *win);
183 #ifdef MODEST_TOOLKIT_HILDON2
184 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
185 TnyFolderStore *dst_folder,
190 static void modest_ui_actions_on_window_move_to (GtkAction *action,
191 TnyList *list_to_move,
192 TnyFolderStore *dst_folder,
196 * This function checks whether a TnyFolderStore is a pop account
199 remote_folder_has_leave_on_server (TnyFolderStore *folder)
204 g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
206 account = get_account_from_folder_store (folder);
207 result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
208 modest_tny_account_get_protocol_type (account)));
209 g_object_unref (account);
214 /* FIXME: this should be merged with the similar code in modest-account-view-window */
215 /* Show the account creation wizard dialog.
216 * returns: TRUE if an account was created. FALSE if the user cancelled.
219 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
221 gboolean result = FALSE;
223 gint dialog_response;
225 /* there is no such wizard yet */
226 wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
227 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
229 #ifndef MODEST_TOOLKIT_HILDON2
230 /* always present a main window in the background
231 * we do it here, so we cannot end up with two wizards (as this
232 * function might be called in modest_window_mgr_get_main_window as well */
234 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
235 TRUE); /* create if not existent */
239 ModestWindowMgr *mgr;
241 mgr = modest_runtime_get_window_mgr ();
243 window_list = modest_window_mgr_get_window_list (mgr);
244 if (window_list == NULL) {
245 win = MODEST_WINDOW (modest_accounts_window_new ());
246 if (modest_window_mgr_register_window (mgr, win, NULL)) {
247 gtk_widget_show_all (GTK_WIDGET (win));
249 gtk_widget_destroy (GTK_WIDGET (win));
254 g_list_free (window_list);
260 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
262 /* make sure the mainwindow is visible. We need to present the
263 wizard again to give it the focus back. show_all are needed
264 in order to get the widgets properly drawn (MainWindow main
265 paned won't be in its right position and the dialog will be
267 #ifndef MODEST_TOOLKIT_HILDON2
268 gtk_widget_show_all (GTK_WIDGET (win));
269 gtk_widget_show_all (GTK_WIDGET (wizard));
270 gtk_window_present (GTK_WINDOW (win));
271 gtk_window_present (GTK_WINDOW (wizard));
274 dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
275 gtk_widget_destroy (GTK_WIDGET (wizard));
276 if (gtk_events_pending ())
277 gtk_main_iteration ();
279 if (dialog_response == GTK_RESPONSE_CANCEL) {
282 /* Check whether an account was created: */
283 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
290 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
293 const gchar *authors[] = {
294 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
297 about = gtk_about_dialog_new ();
298 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
299 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
300 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
301 _("Copyright (c) 2006, Nokia Corporation\n"
302 "All rights reserved."));
303 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
304 _("a modest e-mail client\n\n"
305 "design and implementation: Dirk-Jan C. Binnema\n"
306 "contributions from the fine people at KC and Ig\n"
307 "uses the tinymail email framework written by Philip van Hoof"));
308 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
309 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
310 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
311 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
313 gtk_dialog_run (GTK_DIALOG (about));
314 gtk_widget_destroy(about);
318 * Gets the list of currently selected messages. If the win is the
319 * main window, then it returns a newly allocated list of the headers
320 * selected in the header view. If win is the msg view window, then
321 * the value returned is a list with just a single header.
323 * The caller of this funcion must free the list.
326 get_selected_headers (ModestWindow *win)
328 if (MODEST_IS_MAIN_WINDOW(win)) {
329 GtkWidget *header_view;
331 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
332 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
333 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
335 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
336 /* for MsgViewWindows, we simply return a list with one element */
338 TnyList *list = NULL;
340 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
341 if (header != NULL) {
342 list = tny_simple_list_new ();
343 tny_list_prepend (list, G_OBJECT(header));
344 g_object_unref (G_OBJECT(header));
349 #ifdef MODEST_TOOLKIT_HILDON2
350 } else if (MODEST_IS_HEADER_WINDOW (win)) {
351 GtkWidget *header_view;
353 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
354 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
360 static GtkTreeRowReference *
361 get_next_after_selected_headers (ModestHeaderView *header_view)
363 GtkTreeSelection *sel;
364 GList *selected_rows, *node;
366 GtkTreeRowReference *result;
369 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
370 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
371 selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
373 if (selected_rows == NULL)
376 node = g_list_last (selected_rows);
377 path = gtk_tree_path_copy ((GtkTreePath *) node->data);
378 gtk_tree_path_next (path);
380 result = gtk_tree_row_reference_new (model, path);
382 gtk_tree_path_free (path);
383 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
384 g_list_free (selected_rows);
390 headers_action_mark_as_read (TnyHeader *header,
394 TnyHeaderFlags flags;
396 g_return_if_fail (TNY_IS_HEADER(header));
398 flags = tny_header_get_flags (header);
399 if (flags & TNY_HEADER_FLAG_SEEN) return;
400 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
404 headers_action_mark_as_unread (TnyHeader *header,
408 TnyHeaderFlags flags;
410 g_return_if_fail (TNY_IS_HEADER(header));
412 flags = tny_header_get_flags (header);
413 if (flags & TNY_HEADER_FLAG_SEEN) {
414 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
418 /** After deleing a message that is currently visible in a window,
419 * show the next message from the list, or close the window if there are no more messages.
422 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
424 /* Close msg view window or select next */
425 if (!modest_msg_view_window_select_next_message (win) &&
426 !modest_msg_view_window_select_previous_message (win)) {
428 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
434 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
436 modest_ui_actions_on_edit_mode_delete_message (win);
440 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
442 TnyList *header_list = NULL;
443 TnyIterator *iter = NULL;
444 TnyHeader *header = NULL;
445 gchar *message = NULL;
448 ModestWindowMgr *mgr;
449 GtkWidget *header_view = NULL;
450 gboolean retval = TRUE;
452 g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
454 /* Check first if the header view has the focus */
455 if (MODEST_IS_MAIN_WINDOW (win)) {
457 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
458 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
459 if (!gtk_widget_is_focus (header_view))
463 /* Get the headers, either from the header view (if win is the main window),
464 * or from the message view window: */
465 header_list = get_selected_headers (win);
466 if (!header_list) return FALSE;
468 /* Check if any of the headers are already opened, or in the process of being opened */
469 if (MODEST_IS_MAIN_WINDOW (win)) {
470 gint opened_headers = 0;
472 iter = tny_list_create_iterator (header_list);
473 mgr = modest_runtime_get_window_mgr ();
474 while (!tny_iterator_is_done (iter)) {
475 header = TNY_HEADER (tny_iterator_get_current (iter));
477 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
479 g_object_unref (header);
481 tny_iterator_next (iter);
483 g_object_unref (iter);
485 if (opened_headers > 0) {
488 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
491 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
494 g_object_unref (header_list);
500 if (tny_list_get_length(header_list) == 1) {
501 iter = tny_list_create_iterator (header_list);
502 header = TNY_HEADER (tny_iterator_get_current (iter));
505 subject = tny_header_dup_subject (header);
507 subject = g_strdup (_("mail_va_no_subject"));
508 desc = g_strdup_printf ("%s", subject);
510 g_object_unref (header);
513 g_object_unref (iter);
515 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
516 tny_list_get_length(header_list)), desc);
518 /* Confirmation dialog */
519 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
523 if (response == GTK_RESPONSE_OK) {
524 ModestWindow *main_window = NULL;
525 ModestWindowMgr *mgr = NULL;
526 GtkTreeModel *model = NULL;
527 GtkTreeSelection *sel = NULL;
528 GList *sel_list = NULL, *tmp = NULL;
529 GtkTreeRowReference *next_row_reference = NULL;
530 GtkTreeRowReference *prev_row_reference = NULL;
531 GtkTreePath *next_path = NULL;
532 GtkTreePath *prev_path = NULL;
533 ModestMailOperation *mail_op = NULL;
535 /* Find last selected row */
536 if (MODEST_IS_MAIN_WINDOW (win)) {
537 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
538 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
539 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
540 for (tmp=sel_list; tmp; tmp=tmp->next) {
541 if (tmp->next == NULL) {
542 prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
543 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
545 gtk_tree_path_prev (prev_path);
546 gtk_tree_path_next (next_path);
548 prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
549 next_row_reference = gtk_tree_row_reference_new (model, next_path);
554 /* Disable window dimming management */
555 modest_window_disable_dimming (MODEST_WINDOW(win));
557 /* Remove each header. If it's a view window header_view == NULL */
558 mail_op = modest_mail_operation_new ((GObject *) win);
559 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
561 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
562 g_object_unref (mail_op);
564 /* Enable window dimming management */
566 gtk_tree_selection_unselect_all (sel);
568 modest_window_enable_dimming (MODEST_WINDOW(win));
570 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
571 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
573 /* Get main window */
574 mgr = modest_runtime_get_window_mgr ();
575 main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
576 } else if (MODEST_IS_MAIN_WINDOW (win)) {
577 /* Move cursor to next row */
580 /* Select next or previous row */
581 if (gtk_tree_row_reference_valid (next_row_reference)) {
582 gtk_tree_selection_select_path (sel, next_path);
584 else if (gtk_tree_row_reference_valid (prev_row_reference)) {
585 gtk_tree_selection_select_path (sel, prev_path);
589 if (gtk_tree_row_reference_valid (next_row_reference))
590 gtk_tree_row_reference_free (next_row_reference);
591 if (next_path != NULL)
592 gtk_tree_path_free (next_path);
593 if (gtk_tree_row_reference_valid (prev_row_reference))
594 gtk_tree_row_reference_free (prev_row_reference);
595 if (prev_path != NULL)
596 gtk_tree_path_free (prev_path);
599 /* Update toolbar dimming state */
601 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
602 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
606 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
607 g_list_free (sel_list);
616 g_object_unref (header_list);
624 /* delete either message or folder, based on where we are */
626 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
628 g_return_if_fail (MODEST_IS_WINDOW(win));
630 /* Check first if the header view has the focus */
631 if (MODEST_IS_MAIN_WINDOW (win)) {
633 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
634 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
635 if (gtk_widget_is_focus (w)) {
636 modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
640 modest_ui_actions_on_delete_message (action, win);
644 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
646 ModestWindowMgr *mgr = NULL;
648 #ifdef MODEST_PLATFORM_MAEMO
649 modest_osso_save_state();
650 #endif /* MODEST_PLATFORM_MAEMO */
652 g_debug ("closing down, clearing %d item(s) from operation queue",
653 modest_mail_operation_queue_num_elements
654 (modest_runtime_get_mail_operation_queue()));
656 /* cancel all outstanding operations */
657 modest_mail_operation_queue_cancel_all
658 (modest_runtime_get_mail_operation_queue());
660 g_debug ("queue has been cleared");
663 /* Check if there are opened editing windows */
664 mgr = modest_runtime_get_window_mgr ();
665 modest_window_mgr_close_all_windows (mgr);
667 /* note: when modest-tny-account-store is finalized,
668 it will automatically set all network connections
671 /* gtk_main_quit (); */
675 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
679 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
681 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
682 /* gtk_widget_destroy (GTK_WIDGET (win)); */
683 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
684 /* gboolean ret_value; */
685 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
686 /* } else if (MODEST_IS_WINDOW (win)) { */
687 /* gtk_widget_destroy (GTK_WIDGET (win)); */
689 /* g_return_if_reached (); */
694 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
696 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
698 modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
702 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
704 GtkClipboard *clipboard = NULL;
705 gchar *selection = NULL;
707 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
708 selection = gtk_clipboard_wait_for_text (clipboard);
710 /* Question: why is the clipboard being used here?
711 * It doesn't really make a lot of sense. */
715 modest_address_book_add_address (selection);
721 modest_ui_actions_on_new_account (GtkAction *action,
722 ModestWindow *window)
724 if (!modest_ui_actions_run_account_setup_wizard (window)) {
725 g_debug ("%s: wizard was already running", __FUNCTION__);
730 modest_ui_actions_on_accounts (GtkAction *action,
733 /* This is currently only implemented for Maemo */
734 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
735 if (!modest_ui_actions_run_account_setup_wizard (win))
736 g_debug ("%s: wizard was already running", __FUNCTION__);
740 /* Show the list of accounts */
741 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
743 /* The accounts dialog must be modal */
744 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
745 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
750 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
752 /* This is currently only implemented for Maemo,
753 * because it requires an API (libconic) to detect different connection
756 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
758 /* Create the window if necessary: */
759 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
760 modest_connection_specific_smtp_window_fill_with_connections (
761 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
762 modest_runtime_get_account_mgr());
764 /* Show the window: */
765 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
766 GTK_WINDOW (specific_window), (GtkWindow *) win);
767 gtk_widget_show (specific_window);
768 #endif /* !MODEST_TOOLKIT_GTK */
772 count_part_size (const gchar *part)
774 GnomeVFSURI *vfs_uri;
775 gchar *escaped_filename;
777 GnomeVFSFileInfo *info;
780 /* Estimation of attachment size if we cannot get it from file info */
783 vfs_uri = gnome_vfs_uri_new (part);
785 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
786 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
787 g_free (escaped_filename);
788 gnome_vfs_uri_unref (vfs_uri);
790 info = gnome_vfs_file_info_new ();
792 if (gnome_vfs_get_file_info (part,
794 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
796 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
801 gnome_vfs_file_info_unref (info);
807 count_parts_size (GSList *parts)
812 for (node = parts; node != NULL; node = g_slist_next (node)) {
813 result += count_part_size ((const gchar *) node->data);
820 modest_ui_actions_compose_msg(ModestWindow *win,
823 const gchar *bcc_str,
824 const gchar *subject_str,
825 const gchar *body_str,
827 gboolean set_as_modified)
829 gchar *account_name = NULL;
830 const gchar *mailbox;
832 TnyAccount *account = NULL;
833 TnyFolder *folder = NULL;
834 gchar *from_str = NULL, *signature = NULL, *body = NULL;
835 gchar *recipient = NULL;
836 gboolean use_signature = FALSE;
837 ModestWindow *msg_win = NULL;
838 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
839 ModestTnyAccountStore *store = modest_runtime_get_account_store();
840 GnomeVFSFileSize total_size, allowed_size;
841 guint64 available_disk, expected_size, parts_size;
844 /* we check for low-mem */
845 if (modest_platform_check_memory_low (win, TRUE))
848 available_disk = modest_utils_get_available_space (NULL);
849 parts_count = g_slist_length (attachments);
850 parts_size = count_parts_size (attachments);
851 expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
853 /* Double check: disk full condition or message too big */
854 if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
855 expected_size > available_disk) {
856 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
857 modest_platform_system_banner (NULL, NULL, msg);
863 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
864 modest_platform_run_information_dialog (
866 _FM("sfil_ib_opening_not_allowed"),
872 #ifdef MODEST_TOOLKIT_HILDON2
874 account_name = g_strdup (modest_window_get_active_account(win));
877 account_name = modest_account_mgr_get_default_account(mgr);
880 g_printerr ("modest: no account found\n");
885 mailbox = modest_window_get_active_mailbox (win);
888 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
890 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
893 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
895 g_printerr ("modest: failed to find Drafts folder\n");
898 from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
900 g_printerr ("modest: failed get from string for '%s'\n", account_name);
904 recipient = modest_text_utils_get_email_address (from_str);
905 signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
907 if (body_str != NULL) {
908 body = use_signature ? g_strconcat(body_str, "\n",
909 MODEST_TEXT_UTILS_SIGNATURE_MARKER,
910 "\n", signature, NULL) : g_strdup(body_str);
912 body = use_signature ? g_strconcat("\n", MODEST_TEXT_UTILS_SIGNATURE_MARKER,
913 "\n", signature, NULL) : g_strdup("");
916 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
918 g_printerr ("modest: failed to create new msg\n");
922 /* Create and register edit window */
923 /* This is destroyed by TODO. */
925 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
926 msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
928 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
929 gtk_widget_destroy (GTK_WIDGET (msg_win));
932 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
933 gtk_widget_show_all (GTK_WIDGET (msg_win));
935 while (attachments) {
936 GnomeVFSFileSize att_size;
938 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
939 attachments->data, allowed_size);
940 total_size += att_size;
942 if (att_size > allowed_size) {
943 g_debug ("%s: total size: %u",
944 __FUNCTION__, (unsigned int)total_size);
947 allowed_size -= att_size;
949 attachments = g_slist_next(attachments);
956 g_free (account_name);
958 g_object_unref (G_OBJECT(account));
960 g_object_unref (G_OBJECT(folder));
962 g_object_unref (G_OBJECT(msg));
966 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
968 /* if there are no accounts yet, just show the wizard */
969 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
970 if (!modest_ui_actions_run_account_setup_wizard (win))
973 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
978 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
982 ModestMailOperationStatus status;
984 /* If there is no message or the operation was not successful */
985 status = modest_mail_operation_get_status (mail_op);
986 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
989 /* If it's a memory low issue, then show a banner */
990 error = modest_mail_operation_get_error (mail_op);
991 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
992 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
993 GObject *source = modest_mail_operation_get_source (mail_op);
994 modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
995 _KR("memr_ib_operation_disabled"),
997 g_object_unref (source);
1000 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
1001 error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
1002 gchar *subject, *msg, *format = NULL;
1003 TnyAccount *account;
1004 subject = tny_header_dup_subject (header);
1006 subject = g_strdup (_("mail_va_no_subject"));
1008 account = modest_mail_operation_get_account (mail_op);
1010 ModestProtocol *protocol;
1011 ModestProtocolType proto;
1012 proto = modest_tny_account_get_protocol_type (account);
1013 protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1015 format = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1016 g_object_unref (account);
1020 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1022 msg = g_strdup_printf (format, subject);
1023 modest_platform_run_information_dialog (NULL, msg, FALSE);
1029 /* Remove the header from the preregistered uids */
1030 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1043 } OpenMsgBannerInfo;
1046 GtkTreeModel *model;
1048 OpenMsgBannerInfo *banner_info;
1049 GtkTreeRowReference *rowref;
1053 open_msg_banner_idle (gpointer userdata)
1055 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1057 gdk_threads_enter ();
1058 banner_info->idle_handler = 0;
1059 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1060 if (banner_info->banner)
1061 g_object_ref (banner_info->banner);
1063 gdk_threads_leave ();
1069 get_header_view_from_window (ModestWindow *window)
1071 GtkWidget *header_view;
1073 if (MODEST_IS_MAIN_WINDOW (window)) {
1074 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1075 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1076 #ifdef MODEST_TOOLKIT_HILDON2
1077 } else if (MODEST_IS_HEADER_WINDOW (window)){
1078 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1088 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1091 gchar *account = NULL;
1092 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1097 folder = tny_header_get_folder (header);
1098 /* Gets folder type (OUTBOX headers will be opened in edit window */
1099 if (modest_tny_folder_is_local_folder (folder)) {
1100 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1101 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1102 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1105 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1106 TnyTransportAccount *traccount = NULL;
1107 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1108 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1110 ModestTnySendQueue *send_queue = NULL;
1111 ModestTnySendQueueStatus status;
1113 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1114 TNY_ACCOUNT(traccount)));
1115 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1116 if (TNY_IS_SEND_QUEUE (send_queue)) {
1117 msg_id = modest_tny_send_queue_get_msg_id (header);
1118 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1120 /* Only open messages in outbox with the editor if they are in Failed state */
1121 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1124 #ifdef MODEST_TOOLKIT_HILDON2
1126 /* In Fremantle we can not
1127 open any message from
1128 outbox which is not in
1134 g_object_unref(traccount);
1136 g_warning("Cannot get transport account for message in outbox!!");
1138 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1139 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1143 TnyAccount *acc = tny_folder_get_account (folder);
1146 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1147 g_object_unref (acc);
1151 g_object_unref (folder);
1157 open_msg_cb (ModestMailOperation *mail_op,
1164 ModestWindowMgr *mgr = NULL;
1165 ModestWindow *parent_win = NULL;
1166 ModestWindow *win = NULL;
1167 gchar *account = NULL;
1168 gboolean open_in_editor = FALSE;
1170 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1172 /* Do nothing if there was any problem with the mail
1173 operation. The error will be shown by the error_handler of
1174 the mail operation */
1175 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1178 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1180 /* Mark header as read */
1181 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1183 account = get_info_from_header (header, &open_in_editor, &can_open);
1187 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1189 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1191 if (open_in_editor) {
1192 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1193 gchar *from_header = NULL, *acc_name;
1194 gchar *mailbox = NULL;
1196 from_header = tny_header_dup_from (header);
1198 /* we cannot edit without a valid account... */
1199 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1200 if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1201 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1203 g_free (from_header);
1208 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1209 g_free (from_header);
1215 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1219 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1220 const gchar *mailbox = NULL;
1222 if (parent_win && MODEST_IS_WINDOW (parent_win))
1223 mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1225 if (helper->rowref && helper->model) {
1226 win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1227 helper->model, helper->rowref);
1229 win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1234 /* Register and show new window */
1236 mgr = modest_runtime_get_window_mgr ();
1237 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1238 gtk_widget_destroy (GTK_WIDGET (win));
1241 gtk_widget_show_all (GTK_WIDGET(win));
1244 /* Update toolbar dimming state */
1245 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1252 g_object_unref (parent_win);
1256 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1259 const GError *error;
1260 GObject *win = NULL;
1261 ModestMailOperationStatus status;
1263 win = modest_mail_operation_get_source (mail_op);
1264 error = modest_mail_operation_get_error (mail_op);
1265 status = modest_mail_operation_get_status (mail_op);
1267 /* If the mail op has been cancelled then it's not an error:
1268 don't show any message */
1269 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1270 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1271 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1272 (GError *) error, account)) {
1273 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1274 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1276 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1277 modest_platform_information_banner ((GtkWidget *) win,
1278 NULL, _("emev_ui_imap_inbox_select_error"));
1279 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1280 error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1281 modest_platform_information_banner ((GtkWidget *) win,
1282 NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1283 } else if (user_data) {
1284 modest_platform_information_banner ((GtkWidget *) win,
1288 g_object_unref (account);
1292 g_object_unref (win);
1296 * Returns the account a list of headers belongs to. It returns a
1297 * *new* reference so don't forget to unref it
1300 get_account_from_header_list (TnyList *headers)
1302 TnyAccount *account = NULL;
1304 if (tny_list_get_length (headers) > 0) {
1305 TnyIterator *iter = tny_list_create_iterator (headers);
1306 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1307 TnyFolder *folder = tny_header_get_folder (header);
1310 g_object_unref (header);
1312 while (!tny_iterator_is_done (iter)) {
1313 header = TNY_HEADER (tny_iterator_get_current (iter));
1314 folder = tny_header_get_folder (header);
1317 g_object_unref (header);
1319 tny_iterator_next (iter);
1324 account = tny_folder_get_account (folder);
1325 g_object_unref (folder);
1329 g_object_unref (header);
1331 g_object_unref (iter);
1337 get_account_from_header (TnyHeader *header)
1339 TnyAccount *account = NULL;
1342 folder = tny_header_get_folder (header);
1345 account = tny_folder_get_account (folder);
1346 g_object_unref (folder);
1352 open_msg_helper_destroyer (gpointer user_data)
1354 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1356 if (helper->banner_info) {
1357 g_free (helper->banner_info->message);
1358 if (helper->banner_info->idle_handler > 0) {
1359 g_source_remove (helper->banner_info->idle_handler);
1360 helper->banner_info->idle_handler = 0;
1362 if (helper->banner_info->banner != NULL) {
1363 gtk_widget_destroy (helper->banner_info->banner);
1364 g_object_unref (helper->banner_info->banner);
1365 helper->banner_info->banner = NULL;
1367 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1368 helper->banner_info = NULL;
1370 g_object_unref (helper->model);
1371 g_object_unref (helper->header);
1372 gtk_tree_row_reference_free (helper->rowref);
1373 g_slice_free (OpenMsgHelper, helper);
1377 open_msg_performer(gboolean canceled,
1379 GtkWindow *parent_window,
1380 TnyAccount *account,
1383 ModestMailOperation *mail_op = NULL;
1384 gchar *error_msg = NULL;
1385 ModestProtocolType proto;
1386 TnyConnectionStatus status;
1387 OpenMsgHelper *helper = NULL;
1388 ModestProtocol *protocol;
1389 ModestProtocolRegistry *protocol_registry;
1392 helper = (OpenMsgHelper *) user_data;
1394 status = tny_account_get_connection_status (account);
1395 if (err || canceled) {
1396 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1397 /* Free the helper */
1398 open_msg_helper_destroyer (helper);
1400 /* In disk full conditions we could get this error here */
1401 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1402 (GtkWidget *) parent_window, err,
1408 /* Get the error message depending on the protocol */
1409 proto = modest_tny_account_get_protocol_type (account);
1410 if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1411 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1414 protocol_registry = modest_runtime_get_protocol_registry ();
1415 subject = tny_header_dup_subject (helper->header);
1417 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1418 error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1422 if (error_msg == NULL) {
1423 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1426 #ifndef MODEST_TOOLKIT_HILDON2
1427 gboolean show_open_draft = FALSE;
1428 if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1430 MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1432 TnyFolderType folder_type;
1434 folder = tny_header_get_folder (helper->header);
1435 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1436 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1437 g_object_unref (folder);
1441 #ifdef MODEST_TOOLKIT_HILDON2
1444 gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1447 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1448 g_free (account_name);
1449 open_msg_helper_destroyer (helper);
1454 ModestWindow *window;
1455 GtkWidget *header_view;
1458 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1459 uid = modest_tny_folder_get_header_unique_id (helper->header);
1461 const gchar *mailbox = NULL;
1462 mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1463 window = modest_msg_view_window_new_from_header_view
1464 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1465 if (window != NULL) {
1466 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1468 gtk_widget_destroy (GTK_WIDGET (window));
1470 gtk_widget_show_all (GTK_WIDGET(window));
1474 g_free (account_name);
1476 open_msg_helper_destroyer (helper);
1479 g_free (account_name);
1481 /* Create the mail operation */
1483 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1484 modest_ui_actions_disk_operations_error_handler,
1485 g_strdup (error_msg), g_free);
1486 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1490 #ifndef MODEST_TOOLKIT_HILDON2
1491 if (show_open_draft) {
1492 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1493 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1494 helper->banner_info->banner = NULL;
1495 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1496 helper->banner_info);
1502 headers = TNY_LIST (tny_simple_list_new ());
1503 tny_list_prepend (headers, G_OBJECT (helper->header));
1504 modest_mail_operation_get_msgs_full (mail_op,
1508 open_msg_helper_destroyer);
1509 g_object_unref (headers);
1516 g_object_unref (mail_op);
1517 g_object_unref (account);
1521 * This function is used by both modest_ui_actions_on_open and
1522 * modest_ui_actions_on_header_activated. This way we always do the
1523 * same when trying to open messages.
1526 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1528 ModestWindowMgr *mgr = NULL;
1529 TnyAccount *account;
1530 gboolean cached = FALSE;
1532 GtkWidget *header_view = NULL;
1533 OpenMsgHelper *helper;
1534 ModestWindow *window;
1536 g_return_if_fail (header != NULL && rowref != NULL);
1538 mgr = modest_runtime_get_window_mgr ();
1541 header_view = get_header_view_from_window (MODEST_WINDOW (win));
1542 if (header_view == NULL)
1545 /* Get the account */
1546 account = get_account_from_header (header);
1551 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1553 /* Do not open again the message and present the
1554 window to the user */
1557 #ifndef MODEST_TOOLKIT_HILDON2
1558 gtk_window_present (GTK_WINDOW (window));
1561 /* the header has been registered already, we don't do
1562 * anything but wait for the window to come up*/
1563 g_debug ("header %p already registered, waiting for window", header);
1568 /* Open each message */
1569 cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1571 /* Allways download if we are online. */
1572 if (!tny_device_is_online (modest_runtime_get_device ())) {
1575 /* If ask for user permission to download the messages */
1576 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1577 _("mcen_nc_get_msg"));
1579 /* End if the user does not want to continue */
1580 if (response == GTK_RESPONSE_CANCEL) {
1586 /* We register the window for opening */
1587 modest_window_mgr_register_header (mgr, header, NULL);
1589 /* Create the helper. We need to get a reference to the model
1590 here because it could change while the message is readed
1591 (the user could switch between folders) */
1592 helper = g_slice_new (OpenMsgHelper);
1593 helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1594 helper->header = g_object_ref (header);
1595 helper->rowref = gtk_tree_row_reference_copy (rowref);
1596 helper->banner_info = NULL;
1598 /* Connect to the account and perform */
1600 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1601 open_msg_performer, helper);
1603 /* Call directly the performer, do not need to connect */
1604 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1605 g_object_ref (account), helper);
1610 g_object_unref (account);
1614 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1621 /* we check for low-mem; in that case, show a warning, and don't allow
1624 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1628 headers = get_selected_headers (win);
1632 headers_count = tny_list_get_length (headers);
1633 if (headers_count != 1) {
1634 if (headers_count > 1) {
1635 /* Don't allow activation if there are more than one message selected */
1636 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1639 g_object_unref (headers);
1643 iter = tny_list_create_iterator (headers);
1644 header = TNY_HEADER (tny_iterator_get_current (iter));
1645 g_object_unref (iter);
1649 open_msg_from_header (header, NULL, win);
1650 g_object_unref (header);
1653 g_object_unref(headers);
1657 rf_helper_window_closed (gpointer data,
1660 ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1662 helper->parent_window = NULL;
1665 static ReplyForwardHelper*
1666 create_reply_forward_helper (ReplyForwardAction action,
1668 guint reply_forward_type,
1671 ReplyForwardHelper *rf_helper = NULL;
1672 const gchar *active_acc = modest_window_get_active_account (win);
1673 const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1675 rf_helper = g_slice_new0 (ReplyForwardHelper);
1676 rf_helper->reply_forward_type = reply_forward_type;
1677 rf_helper->action = action;
1678 rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1679 rf_helper->header = (header) ? g_object_ref (header) : NULL;
1680 rf_helper->account_name = (active_acc) ?
1681 g_strdup (active_acc) :
1682 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1683 rf_helper->mailbox = g_strdup (active_mailbox);
1685 /* Note that window could be destroyed just AFTER calling
1686 register_window so we must ensure that this pointer does
1687 not hold invalid references */
1688 if (rf_helper->parent_window)
1689 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1690 rf_helper_window_closed, rf_helper);
1696 free_reply_forward_helper (gpointer data)
1698 ReplyForwardHelper *helper;
1700 helper = (ReplyForwardHelper *) data;
1701 g_free (helper->account_name);
1702 g_free (helper->mailbox);
1704 g_object_unref (helper->header);
1705 if (helper->parent_window)
1706 g_object_weak_unref (G_OBJECT (helper->parent_window),
1707 rf_helper_window_closed, helper);
1708 g_slice_free (ReplyForwardHelper, helper);
1712 reply_forward_cb (ModestMailOperation *mail_op,
1719 TnyMsg *new_msg = NULL;
1720 ReplyForwardHelper *rf_helper;
1721 ModestWindow *msg_win = NULL;
1722 ModestEditType edit_type;
1724 TnyAccount *account = NULL;
1725 ModestWindowMgr *mgr = NULL;
1726 gchar *signature = NULL;
1727 gboolean use_signature;
1730 /* If there was any error. The mail operation could be NULL,
1731 this means that we already have the message downloaded and
1732 that we didn't do a mail operation to retrieve it */
1733 rf_helper = (ReplyForwardHelper *) user_data;
1734 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1737 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1738 rf_helper->account_name, rf_helper->mailbox);
1739 recipient = modest_text_utils_get_email_address (from);
1740 signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(),
1745 /* Create reply mail */
1746 switch (rf_helper->action) {
1749 modest_tny_msg_create_reply_msg (msg, header, from,
1750 (use_signature) ? signature : NULL,
1751 rf_helper->reply_forward_type,
1752 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1754 case ACTION_REPLY_TO_ALL:
1756 modest_tny_msg_create_reply_msg (msg, header, from,
1757 (use_signature) ? signature : NULL,
1758 rf_helper->reply_forward_type,
1759 MODEST_TNY_MSG_REPLY_MODE_ALL);
1760 edit_type = MODEST_EDIT_TYPE_REPLY;
1762 case ACTION_FORWARD:
1764 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1765 rf_helper->reply_forward_type);
1766 edit_type = MODEST_EDIT_TYPE_FORWARD;
1769 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1771 g_return_if_reached ();
1779 g_warning ("%s: failed to create message\n", __FUNCTION__);
1783 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1784 rf_helper->account_name,
1785 TNY_ACCOUNT_TYPE_STORE);
1787 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1791 /* Create and register the windows */
1792 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1793 mgr = modest_runtime_get_window_mgr ();
1794 modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1796 /* Note that register_window could have deleted the account */
1797 if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1798 gdouble parent_zoom;
1800 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1801 modest_window_set_zoom (msg_win, parent_zoom);
1804 /* Show edit window */
1805 gtk_widget_show_all (GTK_WIDGET (msg_win));
1808 /* We always unregister the header because the message is
1809 forwarded or replied so the original one is no longer
1811 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1814 g_object_unref (G_OBJECT (new_msg));
1816 g_object_unref (G_OBJECT (account));
1817 free_reply_forward_helper (rf_helper);
1820 /* Checks a list of headers. If any of them are not currently
1821 * downloaded (CACHED) then returns TRUE else returns FALSE.
1824 header_list_count_uncached_msgs (TnyList *header_list)
1827 gint uncached_messages = 0;
1829 iter = tny_list_create_iterator (header_list);
1830 while (!tny_iterator_is_done (iter)) {
1833 header = TNY_HEADER (tny_iterator_get_current (iter));
1835 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1836 uncached_messages ++;
1837 g_object_unref (header);
1840 tny_iterator_next (iter);
1842 g_object_unref (iter);
1844 return uncached_messages;
1847 /* Returns FALSE if the user does not want to download the
1848 * messages. Returns TRUE if the user allowed the download.
1851 connect_to_get_msg (ModestWindow *win,
1852 gint num_of_uncached_msgs,
1853 TnyAccount *account)
1855 GtkResponseType response;
1857 /* Allways download if we are online. */
1858 if (tny_device_is_online (modest_runtime_get_device ()))
1861 /* If offline, then ask for user permission to download the messages */
1862 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1863 ngettext("mcen_nc_get_msg",
1865 num_of_uncached_msgs));
1867 if (response == GTK_RESPONSE_CANCEL)
1870 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1874 reply_forward_performer (gboolean canceled,
1876 GtkWindow *parent_window,
1877 TnyAccount *account,
1880 ReplyForwardHelper *rf_helper = NULL;
1881 ModestMailOperation *mail_op;
1883 rf_helper = (ReplyForwardHelper *) user_data;
1885 if (canceled || err) {
1886 free_reply_forward_helper (rf_helper);
1890 /* Retrieve the message */
1891 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1892 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1893 modest_ui_actions_disk_operations_error_handler,
1895 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1896 modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1899 g_object_unref(mail_op);
1903 * Common code for the reply and forward actions
1906 reply_forward (ReplyForwardAction action, ModestWindow *win)
1908 ReplyForwardHelper *rf_helper = NULL;
1909 guint reply_forward_type;
1911 g_return_if_fail (MODEST_IS_WINDOW(win));
1913 /* we check for low-mem; in that case, show a warning, and don't allow
1914 * reply/forward (because it could potentially require a lot of memory */
1915 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1919 /* we need an account when editing */
1920 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1921 if (!modest_ui_actions_run_account_setup_wizard (win))
1925 reply_forward_type =
1926 modest_conf_get_int (modest_runtime_get_conf (),
1927 (action == ACTION_FORWARD) ?
1928 MODEST_CONF_FORWARD_TYPE :
1929 MODEST_CONF_REPLY_TYPE,
1932 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1934 TnyHeader *header = NULL;
1935 /* Get header and message. Do not free them here, the
1936 reply_forward_cb must do it */
1937 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1938 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1940 if (msg && header) {
1942 rf_helper = create_reply_forward_helper (action, win,
1943 reply_forward_type, header);
1944 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1946 g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1950 g_object_unref (msg);
1952 g_object_unref (header);
1954 TnyHeader *header = NULL;
1956 gboolean do_retrieve = TRUE;
1957 TnyList *header_list = NULL;
1959 header_list = get_selected_headers (win);
1962 /* Check that only one message is selected for replying */
1963 if (tny_list_get_length (header_list) != 1) {
1964 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1965 NULL, _("mcen_ib_select_one_message"));
1966 g_object_unref (header_list);
1970 /* Only reply/forward to one message */
1971 iter = tny_list_create_iterator (header_list);
1972 header = TNY_HEADER (tny_iterator_get_current (iter));
1973 g_object_unref (iter);
1975 /* Retrieve messages */
1976 do_retrieve = (action == ACTION_FORWARD) ||
1977 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1980 TnyAccount *account = NULL;
1981 TnyFolder *folder = NULL;
1982 gdouble download = TRUE;
1983 guint uncached_msgs = 0;
1985 folder = tny_header_get_folder (header);
1987 goto do_retrieve_frees;
1988 account = tny_folder_get_account (folder);
1990 goto do_retrieve_frees;
1992 uncached_msgs = header_list_count_uncached_msgs (header_list);
1994 if (uncached_msgs > 0) {
1995 /* Allways download if we are online. */
1996 if (!tny_device_is_online (modest_runtime_get_device ())) {
1999 /* If ask for user permission to download the messages */
2000 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2001 ngettext("mcen_nc_get_msg",
2005 /* End if the user does not want to continue */
2006 if (response == GTK_RESPONSE_CANCEL)
2013 rf_helper = create_reply_forward_helper (action, win,
2014 reply_forward_type, header);
2015 if (uncached_msgs > 0) {
2016 modest_platform_connect_and_perform (GTK_WINDOW (win),
2018 reply_forward_performer,
2021 reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2022 account, rf_helper);
2027 g_object_unref (account);
2029 g_object_unref (folder);
2031 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
2034 g_object_unref (header_list);
2035 g_object_unref (header);
2040 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2042 g_return_if_fail (MODEST_IS_WINDOW(win));
2044 reply_forward (ACTION_REPLY, win);
2048 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2050 g_return_if_fail (MODEST_IS_WINDOW(win));
2052 reply_forward (ACTION_FORWARD, win);
2056 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2058 g_return_if_fail (MODEST_IS_WINDOW(win));
2060 reply_forward (ACTION_REPLY_TO_ALL, win);
2064 modest_ui_actions_on_next (GtkAction *action,
2065 ModestWindow *window)
2067 if (MODEST_IS_MAIN_WINDOW (window)) {
2068 GtkWidget *header_view;
2070 header_view = modest_main_window_get_child_widget (
2071 MODEST_MAIN_WINDOW(window),
2072 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2076 modest_header_view_select_next (
2077 MODEST_HEADER_VIEW(header_view));
2078 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2079 modest_msg_view_window_select_next_message (
2080 MODEST_MSG_VIEW_WINDOW (window));
2082 g_return_if_reached ();
2087 modest_ui_actions_on_prev (GtkAction *action,
2088 ModestWindow *window)
2090 g_return_if_fail (MODEST_IS_WINDOW(window));
2092 if (MODEST_IS_MAIN_WINDOW (window)) {
2093 GtkWidget *header_view;
2094 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2095 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2099 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2100 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2101 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2103 g_return_if_reached ();
2108 modest_ui_actions_on_sort (GtkAction *action,
2109 ModestWindow *window)
2111 GtkWidget *header_view = NULL;
2113 g_return_if_fail (MODEST_IS_WINDOW(window));
2115 if (MODEST_IS_MAIN_WINDOW (window)) {
2116 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2117 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2118 #ifdef MODEST_TOOLKIT_HILDON2
2119 } else if (MODEST_IS_HEADER_WINDOW (window)) {
2120 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2125 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2130 /* Show sorting dialog */
2131 modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2135 new_messages_arrived (ModestMailOperation *self,
2136 TnyList *new_headers,
2140 gboolean show_visual_notifications;
2142 source = modest_mail_operation_get_source (self);
2143 show_visual_notifications = (source) ? FALSE : TRUE;
2145 g_object_unref (source);
2147 /* Notify new messages have been downloaded. If the
2148 send&receive was invoked by the user then do not show any
2149 visual notification, only play a sound and activate the LED
2150 (for the Maemo version) */
2151 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2153 /* We only notify about really new messages (not seen) we get */
2154 TnyList *actually_new_list;
2155 TnyIterator *iterator;
2156 actually_new_list = TNY_LIST (tny_simple_list_new ());
2157 for (iterator = tny_list_create_iterator (new_headers);
2158 !tny_iterator_is_done (iterator);
2159 tny_iterator_next (iterator)) {
2161 TnyHeaderFlags flags;
2162 header = TNY_HEADER (tny_iterator_get_current (iterator));
2163 flags = tny_header_get_flags (header);
2165 if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2166 tny_list_append (actually_new_list, G_OBJECT (header));
2168 g_object_unref (header);
2170 g_object_unref (iterator);
2172 if (tny_list_get_length (actually_new_list) > 0) {
2173 GList *new_headers_list = NULL;
2175 new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2177 /* Send notifications */
2178 if (new_headers_list) {
2179 modest_platform_on_new_headers_received (new_headers_list,
2180 show_visual_notifications);
2182 modest_utils_free_notification_list (new_headers_list);
2185 g_object_unref (actually_new_list);
2191 retrieve_all_messages_cb (GObject *source,
2193 guint retrieve_limit)
2199 window = GTK_WINDOW (source);
2200 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2201 num_msgs, retrieve_limit);
2203 /* Ask the user if they want to retrieve all the messages */
2205 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2206 _("mcen_bd_get_all"),
2207 _("mcen_bd_newest_only"));
2208 /* Free and return */
2210 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2214 TnyAccount *account;
2216 gchar *account_name;
2217 gboolean poke_status;
2218 gboolean interactive;
2219 ModestMailOperation *mail_op;
2223 do_send_receive_performer (gboolean canceled,
2225 GtkWindow *parent_window,
2226 TnyAccount *account,
2229 SendReceiveInfo *info;
2231 info = (SendReceiveInfo *) user_data;
2233 if (err || canceled) {
2234 /* In disk full conditions we could get this error here */
2235 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2236 (GtkWidget *) parent_window, err,
2239 if (info->mail_op) {
2240 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2246 /* Set send/receive operation in progress */
2247 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2248 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2251 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2252 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2253 G_CALLBACK (on_send_receive_finished),
2256 /* Send & receive. */
2257 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2258 (info->win) ? retrieve_all_messages_cb : NULL,
2259 new_messages_arrived, info->win);
2264 g_object_unref (G_OBJECT (info->mail_op));
2265 if (info->account_name)
2266 g_free (info->account_name);
2268 g_object_unref (info->win);
2270 g_object_unref (info->account);
2271 g_slice_free (SendReceiveInfo, info);
2275 * This function performs the send & receive required actions. The
2276 * window is used to create the mail operation. Typically it should
2277 * always be the main window, but we pass it as argument in order to
2281 modest_ui_actions_do_send_receive (const gchar *account_name,
2282 gboolean force_connection,
2283 gboolean poke_status,
2284 gboolean interactive,
2287 gchar *acc_name = NULL;
2288 SendReceiveInfo *info;
2289 ModestTnyAccountStore *acc_store;
2290 TnyAccount *account;
2292 /* If no account name was provided then get the current account, and if
2293 there is no current account then pick the default one: */
2294 if (!account_name) {
2296 acc_name = g_strdup (modest_window_get_active_account (win));
2298 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2300 g_printerr ("modest: cannot get default account\n");
2304 acc_name = g_strdup (account_name);
2307 acc_store = modest_runtime_get_account_store ();
2308 account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2310 /* Do not automatically refresh accounts that are flagged as
2311 NO_AUTO_UPDATE. This could be useful for accounts that
2312 handle their own update times */
2314 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2315 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2316 const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2317 ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2319 if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2320 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2321 g_object_unref (account);
2328 /* Create the info for the connect and perform */
2329 info = g_slice_new (SendReceiveInfo);
2330 info->account_name = acc_name;
2331 info->win = (win) ? g_object_ref (win) : NULL;
2332 info->poke_status = poke_status;
2333 info->interactive = interactive;
2334 info->account = account;
2335 /* We need to create the operation here, because otherwise it
2336 could happen that the queue emits the queue-empty signal
2337 while we're trying to connect the account */
2338 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2339 modest_ui_actions_disk_operations_error_handler,
2341 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2343 /* Invoke the connect and perform */
2344 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2345 force_connection, info->account,
2346 do_send_receive_performer, info);
2351 modest_ui_actions_do_cancel_send (const gchar *account_name,
2354 TnyTransportAccount *transport_account;
2355 TnySendQueue *send_queue = NULL;
2356 GError *error = NULL;
2358 /* Get transport account */
2360 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2361 (modest_runtime_get_account_store(),
2363 TNY_ACCOUNT_TYPE_TRANSPORT));
2364 if (!transport_account) {
2365 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2370 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2371 if (!TNY_IS_SEND_QUEUE(send_queue)) {
2372 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2373 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2374 "modest: could not find send queue for account\n");
2376 /* Cancel the current send */
2377 tny_account_cancel (TNY_ACCOUNT (transport_account));
2379 /* Suspend all pending messages */
2380 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2384 if (transport_account != NULL)
2385 g_object_unref (G_OBJECT (transport_account));
2389 modest_ui_actions_cancel_send_all (ModestWindow *win)
2391 GSList *account_names, *iter;
2393 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2396 iter = account_names;
2398 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2399 iter = g_slist_next (iter);
2402 modest_account_mgr_free_account_names (account_names);
2403 account_names = NULL;
2407 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2410 /* Check if accounts exist */
2411 gboolean accounts_exist =
2412 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2414 /* If not, allow the user to create an account before trying to send/receive. */
2415 if (!accounts_exist)
2416 modest_ui_actions_on_accounts (NULL, win);
2418 /* Cancel all sending operaitons */
2419 modest_ui_actions_cancel_send_all (win);
2423 * Refreshes all accounts. This function will be used by automatic
2427 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2428 gboolean force_connection,
2429 gboolean poke_status,
2430 gboolean interactive)
2432 GSList *account_names, *iter;
2434 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2437 iter = account_names;
2439 modest_ui_actions_do_send_receive ((const char*) iter->data,
2441 poke_status, interactive, win);
2442 iter = g_slist_next (iter);
2445 modest_account_mgr_free_account_names (account_names);
2446 account_names = NULL;
2450 * Handler of the click on Send&Receive button in the main toolbar
2453 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2455 /* Check if accounts exist */
2456 gboolean accounts_exist;
2459 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2461 /* If not, allow the user to create an account before trying to send/receive. */
2462 if (!accounts_exist)
2463 modest_ui_actions_on_accounts (NULL, win);
2465 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2466 if (MODEST_IS_MAIN_WINDOW (win)) {
2467 GtkWidget *folder_view;
2468 TnyFolderStore *folder_store;
2471 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2472 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2476 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2479 g_object_unref (folder_store);
2480 /* Refresh the active account. Force the connection if needed
2481 and poke the status of all folders */
2482 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2483 #ifdef MODEST_TOOLKIT_HILDON2
2484 } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2485 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2488 const gchar *active_account;
2489 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2491 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2498 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2501 GtkWidget *header_view;
2503 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2505 header_view = modest_main_window_get_child_widget (main_window,
2506 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2510 conf = modest_runtime_get_conf ();
2512 /* what is saved/restored is depending on the style; thus; we save with
2513 * old style, then update the style, and restore for this new style
2515 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2517 if (modest_header_view_get_style
2518 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2519 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2520 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2522 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2523 MODEST_HEADER_VIEW_STYLE_DETAILS);
2525 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2526 MODEST_CONF_HEADER_VIEW_KEY);
2531 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2533 ModestMainWindow *main_window)
2535 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2536 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2538 /* in the case the folder is empty, show the empty folder message and focus
2540 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2541 if (modest_header_view_is_empty (header_view)) {
2542 TnyFolder *folder = modest_header_view_get_folder (header_view);
2543 GtkWidget *folder_view =
2544 modest_main_window_get_child_widget (main_window,
2545 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2546 if (folder != NULL) {
2547 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2548 g_object_unref (folder);
2550 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2554 /* If no header has been selected then exit */
2559 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2560 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2562 /* Update toolbar dimming state */
2563 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2564 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2568 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2571 ModestWindow *window)
2573 GtkWidget *open_widget;
2574 GtkTreeRowReference *rowref;
2576 g_return_if_fail (MODEST_IS_WINDOW(window));
2577 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2578 g_return_if_fail (TNY_IS_HEADER (header));
2580 if (modest_header_view_count_selected_headers (header_view) > 1) {
2581 /* Don't allow activation if there are more than one message selected */
2582 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2586 /* we check for low-mem; in that case, show a warning, and don't allow
2587 * activating headers
2589 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2592 if (MODEST_IS_MAIN_WINDOW (window)) {
2593 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2594 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2595 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2599 rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2600 open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2601 gtk_tree_row_reference_free (rowref);
2605 set_active_account_from_tny_account (TnyAccount *account,
2606 ModestWindow *window)
2608 const gchar *server_acc_name = tny_account_get_id (account);
2610 /* We need the TnyAccount provided by the
2611 account store because that is the one that
2612 knows the name of the Modest account */
2613 TnyAccount *modest_server_account =
2614 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2615 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2617 if (!modest_server_account) {
2618 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2622 /* Update active account, but only if it's not a pseudo-account */
2623 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2624 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2625 const gchar *modest_acc_name =
2626 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2627 if (modest_acc_name)
2628 modest_window_set_active_account (window, modest_acc_name);
2631 g_object_unref (modest_server_account);
2636 folder_refreshed_cb (ModestMailOperation *mail_op,
2640 ModestMainWindow *win = NULL;
2641 GtkWidget *folder_view, *header_view;
2642 const GError *error;
2644 g_return_if_fail (TNY_IS_FOLDER (folder));
2646 win = MODEST_MAIN_WINDOW (user_data);
2648 /* Check if the operation failed due to memory low conditions */
2649 error = modest_mail_operation_get_error (mail_op);
2650 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2651 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2652 modest_platform_run_information_dialog (GTK_WINDOW (win),
2653 _KR("memr_ib_operation_disabled"),
2659 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2661 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2664 TnyFolderStore *current_folder;
2666 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2667 if (current_folder) {
2668 gboolean different = ((TnyFolderStore *) folder != current_folder);
2669 g_object_unref (current_folder);
2675 /* Check if folder is empty and set headers view contents style */
2676 if ((tny_folder_get_all_count (folder) == 0) ||
2677 modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2678 modest_main_window_set_contents_style (win,
2679 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2683 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2684 TnyFolderStore *folder_store,
2686 ModestMainWindow *main_window)
2688 GtkWidget *header_view;
2690 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2692 header_view = modest_main_window_get_child_widget(main_window,
2693 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2698 if (TNY_IS_ACCOUNT (folder_store)) {
2700 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2702 /* Show account details */
2703 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2706 if (TNY_IS_FOLDER (folder_store) && selected) {
2707 TnyAccount *account;
2709 /* Update the active account */
2710 account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2712 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2713 g_object_unref (account);
2717 /* Set the header style by default, it could
2718 be changed later by the refresh callback to
2720 modest_main_window_set_contents_style (main_window,
2721 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2723 /* Set folder on header view. This function
2724 will call tny_folder_refresh_async so we
2725 pass a callback that will be called when
2726 finished. We use that callback to set the
2727 empty view if there are no messages */
2728 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2729 TNY_FOLDER (folder_store),
2731 MODEST_WINDOW (main_window),
2732 folder_refreshed_cb,
2735 /* Restore configuration. We need to do this
2736 *after* the set_folder because the widget
2737 memory asks the header view about its
2739 modest_widget_memory_restore (modest_runtime_get_conf (),
2740 G_OBJECT(header_view),
2741 MODEST_CONF_HEADER_VIEW_KEY);
2743 /* No need to save the header view
2744 configuration for Maemo because it only
2745 saves the sorting stuff and that it's
2746 already being done by the sort
2747 dialog. Remove it when the GNOME version
2748 has the same behaviour */
2749 #ifdef MODEST_TOOLKIT_GTK
2750 if (modest_main_window_get_contents_style (main_window) ==
2751 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2752 modest_widget_memory_save (modest_runtime_get_conf (),
2753 G_OBJECT (header_view),
2754 MODEST_CONF_HEADER_VIEW_KEY);
2756 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2760 /* Update dimming state */
2761 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2762 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2766 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2773 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2775 online = tny_device_is_online (modest_runtime_get_device());
2778 /* already online -- the item is simply not there... */
2779 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2781 GTK_MESSAGE_WARNING,
2783 _("The %s you selected cannot be found"),
2785 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2786 gtk_dialog_run (GTK_DIALOG(dialog));
2788 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2791 _("mcen_bd_dialog_cancel"),
2792 GTK_RESPONSE_REJECT,
2793 _("mcen_bd_dialog_ok"),
2794 GTK_RESPONSE_ACCEPT,
2796 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2797 "Do you want to get online?"), item);
2798 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2799 gtk_label_new (txt), FALSE, FALSE, 0);
2800 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2803 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2804 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2805 /* TODO: Comment about why is this commented out: */
2806 /* modest_platform_connect_and_wait (); */
2809 gtk_widget_destroy (dialog);
2813 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2816 /* g_debug ("%s %s", __FUNCTION__, link); */
2821 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2824 modest_platform_activate_uri (link);
2828 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2831 modest_platform_show_uri_popup (link);
2835 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2838 /* we check for low-mem; in that case, show a warning, and don't allow
2839 * viewing attachments
2841 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2844 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2848 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2849 const gchar *address,
2852 /* g_debug ("%s %s", __FUNCTION__, address); */
2856 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2857 TnyMsg *saved_draft,
2860 ModestMsgEditWindow *edit_window;
2862 /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2863 #ifndef MODEST_TOOLKIT_HILDON2
2864 ModestMainWindow *win;
2866 /* FIXME. Make the header view sensitive again. This is a
2867 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2869 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2870 modest_runtime_get_window_mgr(), FALSE));
2872 GtkWidget *hdrview = modest_main_window_get_child_widget(
2873 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2874 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2878 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2880 /* Set draft is there was no error */
2881 if (!modest_mail_operation_get_error (mail_op))
2882 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2884 g_object_unref(edit_window);
2888 enough_space_for_message (ModestMsgEditWindow *edit_window,
2891 guint64 available_disk, expected_size;
2896 available_disk = modest_utils_get_available_space (NULL);
2897 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2898 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2903 /* Double check: disk full condition or message too big */
2904 if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2905 expected_size > available_disk) {
2906 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2907 modest_platform_information_banner (NULL, NULL, msg);
2914 * djcb: if we're in low-memory state, we only allow for
2915 * saving messages smaller than
2916 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2917 * should still allow for sending anything critical...
2919 if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2920 modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2924 * djcb: we also make sure that the attachments are smaller than the max size
2925 * this is for the case where we'd try to forward a message with attachments
2926 * bigger than our max allowed size, or sending an message from drafts which
2927 * somehow got past our checks when attaching.
2929 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2930 modest_platform_run_information_dialog (
2931 GTK_WINDOW(edit_window),
2932 _FM("sfil_ib_opening_not_allowed"),
2941 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2943 TnyTransportAccount *transport_account;
2944 ModestMailOperation *mail_operation;
2946 gchar *account_name;
2947 ModestAccountMgr *account_mgr;
2948 gboolean had_error = FALSE;
2949 ModestMainWindow *win = NULL;
2951 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2953 data = modest_msg_edit_window_get_msg_data (edit_window);
2956 if (!enough_space_for_message (edit_window, data)) {
2957 modest_msg_edit_window_free_msg_data (edit_window, data);
2961 account_name = g_strdup (data->account_name);
2962 account_mgr = modest_runtime_get_account_mgr();
2964 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2966 account_name = modest_account_mgr_get_default_account (account_mgr);
2967 if (!account_name) {
2968 g_printerr ("modest: no account found\n");
2969 modest_msg_edit_window_free_msg_data (edit_window, data);
2973 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2974 account_name = g_strdup (data->account_name);
2978 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2979 (modest_runtime_get_account_store (),
2981 TNY_ACCOUNT_TYPE_TRANSPORT));
2982 if (!transport_account) {
2983 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2984 g_free (account_name);
2985 modest_msg_edit_window_free_msg_data (edit_window, data);
2989 /* Create the mail operation */
2990 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2992 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2994 modest_mail_operation_save_to_drafts (mail_operation,
3006 data->priority_flags,
3009 on_save_to_drafts_cb,
3010 g_object_ref(edit_window));
3012 #ifdef MODEST_TOOLKIT_HILDON2
3013 /* In hildon2 we always show the information banner on saving to drafts.
3014 * It will be a system information banner in this case.
3016 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3017 modest_platform_information_banner (NULL, NULL, text);
3020 /* Use the main window as the parent of the banner, if the
3021 main window does not exist it won't be shown, if the parent
3022 window exists then it's properly shown. We don't use the
3023 editor window because it could be closed (save to drafts
3024 could happen after closing the window */
3025 win = (ModestMainWindow *)
3026 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3028 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3029 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3033 modest_msg_edit_window_set_modified (edit_window, FALSE);
3036 g_free (account_name);
3037 g_object_unref (G_OBJECT (transport_account));
3038 g_object_unref (G_OBJECT (mail_operation));
3040 modest_msg_edit_window_free_msg_data (edit_window, data);
3043 * If the drafts folder is selected then make the header view
3044 * insensitive while the message is being saved to drafts
3045 * (it'll be sensitive again in on_save_to_drafts_cb()). This
3046 * is not very clean but it avoids letting the drafts folder
3047 * in an inconsistent state: the user could edit the message
3048 * being saved and undesirable things would happen.
3049 * In the average case the user won't notice anything at
3050 * all. In the worst case (the user is editing a really big
3051 * file from Drafts) the header view will be insensitive
3052 * during the saving process (10 or 20 seconds, depending on
3053 * the message). Anyway this is just a quick workaround: once
3054 * we find a better solution it should be removed
3055 * See NB#65125 (commend #18) for details.
3057 if (!had_error && win != NULL) {
3058 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3059 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3061 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3063 if (modest_tny_folder_is_local_folder(folder)) {
3064 TnyFolderType folder_type;
3065 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3066 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3067 GtkWidget *hdrview = modest_main_window_get_child_widget(
3068 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3069 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3073 if (folder != NULL) g_object_unref(folder);
3080 /* For instance, when clicking the Send toolbar button when editing a message: */
3082 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3084 TnyTransportAccount *transport_account = NULL;
3085 gboolean had_error = FALSE;
3087 ModestAccountMgr *account_mgr;
3088 gchar *account_name;
3089 ModestMailOperation *mail_operation;
3092 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3094 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3097 data = modest_msg_edit_window_get_msg_data (edit_window);
3099 if (data->subject == NULL || data->subject[0] == '\0') {
3100 /* Empty subject -> no send */
3101 modest_msg_edit_window_free_msg_data (edit_window, data);
3105 recipients = g_strconcat (data->to?data->to:"",
3106 data->cc?data->cc:"",
3107 data->bcc?data->bcc:"",
3109 if (recipients == NULL || recipients[0] == '\0') {
3110 /* Empty subject -> no send */
3111 g_free (recipients);
3112 modest_msg_edit_window_free_msg_data (edit_window, data);
3115 g_free (recipients);
3118 if (!enough_space_for_message (edit_window, data)) {
3119 modest_msg_edit_window_free_msg_data (edit_window, data);
3123 account_mgr = modest_runtime_get_account_mgr();
3124 account_name = g_strdup (data->account_name);
3126 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3129 account_name = modest_account_mgr_get_default_account (account_mgr);
3131 if (!account_name) {
3132 modest_msg_edit_window_free_msg_data (edit_window, data);
3133 /* Run account setup wizard */
3134 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3139 /* Get the currently-active transport account for this modest account: */
3140 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3142 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3143 (modest_runtime_get_account_store (),
3144 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3147 if (!transport_account) {
3148 modest_msg_edit_window_free_msg_data (edit_window, data);
3149 /* Run account setup wizard */
3150 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3155 /* Create the mail operation */
3156 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3157 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3159 modest_mail_operation_send_new_mail (mail_operation,
3173 data->priority_flags);
3175 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3176 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3178 if (modest_mail_operation_get_error (mail_operation) != NULL) {
3179 const GError *error = modest_mail_operation_get_error (mail_operation);
3180 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3181 error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3182 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3183 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3189 g_free (account_name);
3190 g_object_unref (G_OBJECT (transport_account));
3191 g_object_unref (G_OBJECT (mail_operation));
3193 modest_msg_edit_window_free_msg_data (edit_window, data);
3196 modest_msg_edit_window_set_sent (edit_window, TRUE);
3198 /* Save settings and close the window: */
3199 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3206 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3207 ModestMsgEditWindow *window)
3209 ModestMsgEditFormatState *format_state = NULL;
3211 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3212 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3214 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3217 format_state = modest_msg_edit_window_get_format_state (window);
3218 g_return_if_fail (format_state != NULL);
3220 format_state->bold = gtk_toggle_action_get_active (action);
3221 modest_msg_edit_window_set_format_state (window, format_state);
3222 g_free (format_state);
3227 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3228 ModestMsgEditWindow *window)
3230 ModestMsgEditFormatState *format_state = NULL;
3232 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3233 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3235 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3238 format_state = modest_msg_edit_window_get_format_state (window);
3239 g_return_if_fail (format_state != NULL);