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--\n", signature, NULL) : g_strdup(body_str);
910 body = use_signature ? g_strconcat("\n--\n", signature, NULL) : g_strdup("");
913 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
915 g_printerr ("modest: failed to create new msg\n");
919 /* Create and register edit window */
920 /* This is destroyed by TODO. */
922 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
923 msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
925 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
926 gtk_widget_destroy (GTK_WIDGET (msg_win));
929 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
930 gtk_widget_show_all (GTK_WIDGET (msg_win));
932 while (attachments) {
933 GnomeVFSFileSize att_size;
935 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
936 attachments->data, allowed_size);
937 total_size += att_size;
939 if (att_size > allowed_size) {
940 g_debug ("%s: total size: %u",
941 __FUNCTION__, (unsigned int)total_size);
944 allowed_size -= att_size;
946 attachments = g_slist_next(attachments);
953 g_free (account_name);
955 g_object_unref (G_OBJECT(account));
957 g_object_unref (G_OBJECT(folder));
959 g_object_unref (G_OBJECT(msg));
963 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
965 /* if there are no accounts yet, just show the wizard */
966 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
967 if (!modest_ui_actions_run_account_setup_wizard (win))
970 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
975 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
979 ModestMailOperationStatus status;
981 /* If there is no message or the operation was not successful */
982 status = modest_mail_operation_get_status (mail_op);
983 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
986 /* If it's a memory low issue, then show a banner */
987 error = modest_mail_operation_get_error (mail_op);
988 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
989 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
990 GObject *source = modest_mail_operation_get_source (mail_op);
991 modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
992 _KR("memr_ib_operation_disabled"),
994 g_object_unref (source);
997 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
998 error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
999 gchar *subject, *msg, *format = NULL;
1000 TnyAccount *account;
1001 subject = tny_header_dup_subject (header);
1003 subject = g_strdup (_("mail_va_no_subject"));
1005 account = modest_mail_operation_get_account (mail_op);
1007 ModestProtocol *protocol;
1008 ModestProtocolType proto;
1009 proto = modest_tny_account_get_protocol_type (account);
1010 protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1012 format = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1013 g_object_unref (account);
1017 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1019 msg = g_strdup_printf (format, subject);
1020 modest_platform_run_information_dialog (NULL, msg, FALSE);
1026 /* Remove the header from the preregistered uids */
1027 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1040 } OpenMsgBannerInfo;
1043 GtkTreeModel *model;
1045 OpenMsgBannerInfo *banner_info;
1046 GtkTreeRowReference *rowref;
1050 open_msg_banner_idle (gpointer userdata)
1052 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1054 gdk_threads_enter ();
1055 banner_info->idle_handler = 0;
1056 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1057 if (banner_info->banner)
1058 g_object_ref (banner_info->banner);
1060 gdk_threads_leave ();
1066 get_header_view_from_window (ModestWindow *window)
1068 GtkWidget *header_view;
1070 if (MODEST_IS_MAIN_WINDOW (window)) {
1071 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1072 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1073 #ifdef MODEST_TOOLKIT_HILDON2
1074 } else if (MODEST_IS_HEADER_WINDOW (window)){
1075 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1085 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1088 gchar *account = NULL;
1089 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1094 folder = tny_header_get_folder (header);
1095 /* Gets folder type (OUTBOX headers will be opened in edit window */
1096 if (modest_tny_folder_is_local_folder (folder)) {
1097 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1098 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1099 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1102 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1103 TnyTransportAccount *traccount = NULL;
1104 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1105 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1107 ModestTnySendQueue *send_queue = NULL;
1108 ModestTnySendQueueStatus status;
1110 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1111 TNY_ACCOUNT(traccount)));
1112 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1113 if (TNY_IS_SEND_QUEUE (send_queue)) {
1114 msg_id = modest_tny_send_queue_get_msg_id (header);
1115 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1117 /* Only open messages in outbox with the editor if they are in Failed state */
1118 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1121 #ifdef MODEST_TOOLKIT_HILDON2
1123 /* In Fremantle we can not
1124 open any message from
1125 outbox which is not in
1131 g_object_unref(traccount);
1133 g_warning("Cannot get transport account for message in outbox!!");
1135 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1136 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1140 TnyAccount *acc = tny_folder_get_account (folder);
1143 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1144 g_object_unref (acc);
1148 g_object_unref (folder);
1154 open_msg_cb (ModestMailOperation *mail_op,
1161 ModestWindowMgr *mgr = NULL;
1162 ModestWindow *parent_win = NULL;
1163 ModestWindow *win = NULL;
1164 gchar *account = NULL;
1165 gboolean open_in_editor = FALSE;
1167 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1169 /* Do nothing if there was any problem with the mail
1170 operation. The error will be shown by the error_handler of
1171 the mail operation */
1172 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1175 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1177 /* Mark header as read */
1178 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1180 account = get_info_from_header (header, &open_in_editor, &can_open);
1184 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1186 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1188 if (open_in_editor) {
1189 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1190 gchar *from_header = NULL, *acc_name;
1191 gchar *mailbox = NULL;
1193 from_header = tny_header_dup_from (header);
1195 /* we cannot edit without a valid account... */
1196 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1197 if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1198 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1200 g_free (from_header);
1205 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1206 g_free (from_header);
1212 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1216 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1217 const gchar *mailbox = NULL;
1219 if (parent_win && MODEST_IS_WINDOW (parent_win))
1220 mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1222 if (helper->rowref && helper->model) {
1223 win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1224 helper->model, helper->rowref);
1226 win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1231 /* Register and show new window */
1233 mgr = modest_runtime_get_window_mgr ();
1234 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1235 gtk_widget_destroy (GTK_WIDGET (win));
1238 gtk_widget_show_all (GTK_WIDGET(win));
1241 /* Update toolbar dimming state */
1242 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1243 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1249 g_object_unref (parent_win);
1253 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1256 const GError *error;
1257 GObject *win = NULL;
1258 ModestMailOperationStatus status;
1260 win = modest_mail_operation_get_source (mail_op);
1261 error = modest_mail_operation_get_error (mail_op);
1262 status = modest_mail_operation_get_status (mail_op);
1264 /* If the mail op has been cancelled then it's not an error:
1265 don't show any message */
1266 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1267 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1268 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1269 (GError *) error, account)) {
1270 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1271 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1273 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1274 modest_platform_information_banner ((GtkWidget *) win,
1275 NULL, _("emev_ui_imap_inbox_select_error"));
1276 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1277 error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1278 modest_platform_information_banner ((GtkWidget *) win,
1279 NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1280 } else if (user_data) {
1281 modest_platform_information_banner ((GtkWidget *) win,
1285 g_object_unref (account);
1289 g_object_unref (win);
1293 * Returns the account a list of headers belongs to. It returns a
1294 * *new* reference so don't forget to unref it
1297 get_account_from_header_list (TnyList *headers)
1299 TnyAccount *account = NULL;
1301 if (tny_list_get_length (headers) > 0) {
1302 TnyIterator *iter = tny_list_create_iterator (headers);
1303 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1304 TnyFolder *folder = tny_header_get_folder (header);
1307 g_object_unref (header);
1309 while (!tny_iterator_is_done (iter)) {
1310 header = TNY_HEADER (tny_iterator_get_current (iter));
1311 folder = tny_header_get_folder (header);
1314 g_object_unref (header);
1316 tny_iterator_next (iter);
1321 account = tny_folder_get_account (folder);
1322 g_object_unref (folder);
1326 g_object_unref (header);
1328 g_object_unref (iter);
1334 get_account_from_header (TnyHeader *header)
1336 TnyAccount *account = NULL;
1339 folder = tny_header_get_folder (header);
1342 account = tny_folder_get_account (folder);
1343 g_object_unref (folder);
1349 open_msg_helper_destroyer (gpointer user_data)
1351 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1353 if (helper->banner_info) {
1354 g_free (helper->banner_info->message);
1355 if (helper->banner_info->idle_handler > 0) {
1356 g_source_remove (helper->banner_info->idle_handler);
1357 helper->banner_info->idle_handler = 0;
1359 if (helper->banner_info->banner != NULL) {
1360 gtk_widget_destroy (helper->banner_info->banner);
1361 g_object_unref (helper->banner_info->banner);
1362 helper->banner_info->banner = NULL;
1364 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1365 helper->banner_info = NULL;
1367 g_object_unref (helper->model);
1368 g_object_unref (helper->header);
1369 gtk_tree_row_reference_free (helper->rowref);
1370 g_slice_free (OpenMsgHelper, helper);
1374 open_msg_performer(gboolean canceled,
1376 GtkWindow *parent_window,
1377 TnyAccount *account,
1380 ModestMailOperation *mail_op = NULL;
1381 gchar *error_msg = NULL;
1382 ModestProtocolType proto;
1383 TnyConnectionStatus status;
1384 OpenMsgHelper *helper = NULL;
1385 ModestProtocol *protocol;
1386 ModestProtocolRegistry *protocol_registry;
1389 helper = (OpenMsgHelper *) user_data;
1391 status = tny_account_get_connection_status (account);
1392 if (err || canceled) {
1393 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1394 /* Free the helper */
1395 open_msg_helper_destroyer (helper);
1397 /* In disk full conditions we could get this error here */
1398 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1399 (GtkWidget *) parent_window, err,
1405 /* Get the error message depending on the protocol */
1406 proto = modest_tny_account_get_protocol_type (account);
1407 if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1408 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1411 protocol_registry = modest_runtime_get_protocol_registry ();
1412 subject = tny_header_dup_subject (helper->header);
1414 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1415 error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1419 if (error_msg == NULL) {
1420 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1423 #ifndef MODEST_TOOLKIT_HILDON2
1424 gboolean show_open_draft = FALSE;
1425 if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1427 MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1429 TnyFolderType folder_type;
1431 folder = tny_header_get_folder (helper->header);
1432 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1433 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1434 g_object_unref (folder);
1438 #ifdef MODEST_TOOLKIT_HILDON2
1441 gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1444 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1445 g_free (account_name);
1446 open_msg_helper_destroyer (helper);
1451 ModestWindow *window;
1452 GtkWidget *header_view;
1455 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1456 uid = modest_tny_folder_get_header_unique_id (helper->header);
1458 const gchar *mailbox = NULL;
1459 mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1460 window = modest_msg_view_window_new_from_header_view
1461 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1462 if (window != NULL) {
1463 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1465 gtk_widget_destroy (GTK_WIDGET (window));
1467 gtk_widget_show_all (GTK_WIDGET(window));
1471 g_free (account_name);
1473 open_msg_helper_destroyer (helper);
1476 g_free (account_name);
1478 /* Create the mail operation */
1480 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1481 modest_ui_actions_disk_operations_error_handler,
1482 g_strdup (error_msg), g_free);
1483 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1487 #ifndef MODEST_TOOLKIT_HILDON2
1488 if (show_open_draft) {
1489 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1490 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1491 helper->banner_info->banner = NULL;
1492 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1493 helper->banner_info);
1499 headers = TNY_LIST (tny_simple_list_new ());
1500 tny_list_prepend (headers, G_OBJECT (helper->header));
1501 modest_mail_operation_get_msgs_full (mail_op,
1505 open_msg_helper_destroyer);
1506 g_object_unref (headers);
1513 g_object_unref (mail_op);
1514 g_object_unref (account);
1518 * This function is used by both modest_ui_actions_on_open and
1519 * modest_ui_actions_on_header_activated. This way we always do the
1520 * same when trying to open messages.
1523 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1525 ModestWindowMgr *mgr = NULL;
1526 TnyAccount *account;
1527 gboolean cached = FALSE;
1529 GtkWidget *header_view = NULL;
1530 OpenMsgHelper *helper;
1531 ModestWindow *window;
1533 g_return_if_fail (header != NULL && rowref != NULL);
1535 mgr = modest_runtime_get_window_mgr ();
1538 header_view = get_header_view_from_window (MODEST_WINDOW (win));
1539 if (header_view == NULL)
1542 /* Get the account */
1543 account = get_account_from_header (header);
1548 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1550 /* Do not open again the message and present the
1551 window to the user */
1554 #ifndef MODEST_TOOLKIT_HILDON2
1555 gtk_window_present (GTK_WINDOW (window));
1558 /* the header has been registered already, we don't do
1559 * anything but wait for the window to come up*/
1560 g_debug ("header %p already registered, waiting for window", header);
1565 /* Open each message */
1566 cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1568 /* Allways download if we are online. */
1569 if (!tny_device_is_online (modest_runtime_get_device ())) {
1572 /* If ask for user permission to download the messages */
1573 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1574 _("mcen_nc_get_msg"));
1576 /* End if the user does not want to continue */
1577 if (response == GTK_RESPONSE_CANCEL) {
1583 /* We register the window for opening */
1584 modest_window_mgr_register_header (mgr, header, NULL);
1586 /* Create the helper. We need to get a reference to the model
1587 here because it could change while the message is readed
1588 (the user could switch between folders) */
1589 helper = g_slice_new (OpenMsgHelper);
1590 helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1591 helper->header = g_object_ref (header);
1592 helper->rowref = gtk_tree_row_reference_copy (rowref);
1593 helper->banner_info = NULL;
1595 /* Connect to the account and perform */
1597 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1598 open_msg_performer, helper);
1600 /* Call directly the performer, do not need to connect */
1601 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1602 g_object_ref (account), helper);
1607 g_object_unref (account);
1611 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1618 /* we check for low-mem; in that case, show a warning, and don't allow
1621 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1625 headers = get_selected_headers (win);
1629 headers_count = tny_list_get_length (headers);
1630 if (headers_count != 1) {
1631 if (headers_count > 1) {
1632 /* Don't allow activation if there are more than one message selected */
1633 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1636 g_object_unref (headers);
1640 iter = tny_list_create_iterator (headers);
1641 header = TNY_HEADER (tny_iterator_get_current (iter));
1642 g_object_unref (iter);
1646 open_msg_from_header (header, NULL, win);
1647 g_object_unref (header);
1650 g_object_unref(headers);
1654 rf_helper_window_closed (gpointer data,
1657 ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1659 helper->parent_window = NULL;
1662 static ReplyForwardHelper*
1663 create_reply_forward_helper (ReplyForwardAction action,
1665 guint reply_forward_type,
1668 ReplyForwardHelper *rf_helper = NULL;
1669 const gchar *active_acc = modest_window_get_active_account (win);
1670 const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1672 rf_helper = g_slice_new0 (ReplyForwardHelper);
1673 rf_helper->reply_forward_type = reply_forward_type;
1674 rf_helper->action = action;
1675 rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1676 rf_helper->header = (header) ? g_object_ref (header) : NULL;
1677 rf_helper->account_name = (active_acc) ?
1678 g_strdup (active_acc) :
1679 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1680 rf_helper->mailbox = g_strdup (active_mailbox);
1682 /* Note that window could be destroyed just AFTER calling
1683 register_window so we must ensure that this pointer does
1684 not hold invalid references */
1685 if (rf_helper->parent_window)
1686 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1687 rf_helper_window_closed, rf_helper);
1693 free_reply_forward_helper (gpointer data)
1695 ReplyForwardHelper *helper;
1697 helper = (ReplyForwardHelper *) data;
1698 g_free (helper->account_name);
1699 g_free (helper->mailbox);
1701 g_object_unref (helper->header);
1702 if (helper->parent_window)
1703 g_object_weak_unref (G_OBJECT (helper->parent_window),
1704 rf_helper_window_closed, helper);
1705 g_slice_free (ReplyForwardHelper, helper);
1709 reply_forward_cb (ModestMailOperation *mail_op,
1716 TnyMsg *new_msg = NULL;
1717 ReplyForwardHelper *rf_helper;
1718 ModestWindow *msg_win = NULL;
1719 ModestEditType edit_type;
1721 TnyAccount *account = NULL;
1722 ModestWindowMgr *mgr = NULL;
1723 gchar *signature = NULL;
1724 gboolean use_signature;
1727 /* If there was any error. The mail operation could be NULL,
1728 this means that we already have the message downloaded and
1729 that we didn't do a mail operation to retrieve it */
1730 rf_helper = (ReplyForwardHelper *) user_data;
1731 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1734 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1735 rf_helper->account_name, rf_helper->mailbox);
1736 recipient = modest_text_utils_get_email_address (from);
1737 signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(),
1742 /* Create reply mail */
1743 switch (rf_helper->action) {
1746 modest_tny_msg_create_reply_msg (msg, header, from,
1747 (use_signature) ? signature : NULL,
1748 rf_helper->reply_forward_type,
1749 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1751 case ACTION_REPLY_TO_ALL:
1753 modest_tny_msg_create_reply_msg (msg, header, from,
1754 (use_signature) ? signature : NULL,
1755 rf_helper->reply_forward_type,
1756 MODEST_TNY_MSG_REPLY_MODE_ALL);
1757 edit_type = MODEST_EDIT_TYPE_REPLY;
1759 case ACTION_FORWARD:
1761 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1762 rf_helper->reply_forward_type);
1763 edit_type = MODEST_EDIT_TYPE_FORWARD;
1766 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1768 g_return_if_reached ();
1776 g_warning ("%s: failed to create message\n", __FUNCTION__);
1780 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1781 rf_helper->account_name,
1782 TNY_ACCOUNT_TYPE_STORE);
1784 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1788 /* Create and register the windows */
1789 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1790 mgr = modest_runtime_get_window_mgr ();
1791 modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1793 /* Note that register_window could have deleted the account */
1794 if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1795 gdouble parent_zoom;
1797 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1798 modest_window_set_zoom (msg_win, parent_zoom);
1801 /* Show edit window */
1802 gtk_widget_show_all (GTK_WIDGET (msg_win));
1805 /* We always unregister the header because the message is
1806 forwarded or replied so the original one is no longer
1808 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1811 g_object_unref (G_OBJECT (new_msg));
1813 g_object_unref (G_OBJECT (account));
1814 free_reply_forward_helper (rf_helper);
1817 /* Checks a list of headers. If any of them are not currently
1818 * downloaded (CACHED) then returns TRUE else returns FALSE.
1821 header_list_count_uncached_msgs (TnyList *header_list)
1824 gint uncached_messages = 0;
1826 iter = tny_list_create_iterator (header_list);
1827 while (!tny_iterator_is_done (iter)) {
1830 header = TNY_HEADER (tny_iterator_get_current (iter));
1832 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1833 uncached_messages ++;
1834 g_object_unref (header);
1837 tny_iterator_next (iter);
1839 g_object_unref (iter);
1841 return uncached_messages;
1844 /* Returns FALSE if the user does not want to download the
1845 * messages. Returns TRUE if the user allowed the download.
1848 connect_to_get_msg (ModestWindow *win,
1849 gint num_of_uncached_msgs,
1850 TnyAccount *account)
1852 GtkResponseType response;
1854 /* Allways download if we are online. */
1855 if (tny_device_is_online (modest_runtime_get_device ()))
1858 /* If offline, then ask for user permission to download the messages */
1859 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1860 ngettext("mcen_nc_get_msg",
1862 num_of_uncached_msgs));
1864 if (response == GTK_RESPONSE_CANCEL)
1867 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1871 reply_forward_performer (gboolean canceled,
1873 GtkWindow *parent_window,
1874 TnyAccount *account,
1877 ReplyForwardHelper *rf_helper = NULL;
1878 ModestMailOperation *mail_op;
1880 rf_helper = (ReplyForwardHelper *) user_data;
1882 if (canceled || err) {
1883 free_reply_forward_helper (rf_helper);
1887 /* Retrieve the message */
1888 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1889 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1890 modest_ui_actions_disk_operations_error_handler,
1892 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1893 modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1896 g_object_unref(mail_op);
1900 * Common code for the reply and forward actions
1903 reply_forward (ReplyForwardAction action, ModestWindow *win)
1905 ReplyForwardHelper *rf_helper = NULL;
1906 guint reply_forward_type;
1908 g_return_if_fail (MODEST_IS_WINDOW(win));
1910 /* we check for low-mem; in that case, show a warning, and don't allow
1911 * reply/forward (because it could potentially require a lot of memory */
1912 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1916 /* we need an account when editing */
1917 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1918 if (!modest_ui_actions_run_account_setup_wizard (win))
1922 reply_forward_type =
1923 modest_conf_get_int (modest_runtime_get_conf (),
1924 (action == ACTION_FORWARD) ?
1925 MODEST_CONF_FORWARD_TYPE :
1926 MODEST_CONF_REPLY_TYPE,
1929 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1931 TnyHeader *header = NULL;
1932 /* Get header and message. Do not free them here, the
1933 reply_forward_cb must do it */
1934 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1935 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1937 if (msg && header) {
1939 rf_helper = create_reply_forward_helper (action, win,
1940 reply_forward_type, header);
1941 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1943 g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1947 g_object_unref (msg);
1949 g_object_unref (header);
1951 TnyHeader *header = NULL;
1953 gboolean do_retrieve = TRUE;
1954 TnyList *header_list = NULL;
1956 header_list = get_selected_headers (win);
1959 /* Check that only one message is selected for replying */
1960 if (tny_list_get_length (header_list) != 1) {
1961 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1962 NULL, _("mcen_ib_select_one_message"));
1963 g_object_unref (header_list);
1967 /* Only reply/forward to one message */
1968 iter = tny_list_create_iterator (header_list);
1969 header = TNY_HEADER (tny_iterator_get_current (iter));
1970 g_object_unref (iter);
1972 /* Retrieve messages */
1973 do_retrieve = (action == ACTION_FORWARD) ||
1974 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1977 TnyAccount *account = NULL;
1978 TnyFolder *folder = NULL;
1979 gdouble download = TRUE;
1980 guint uncached_msgs = 0;
1982 folder = tny_header_get_folder (header);
1984 goto do_retrieve_frees;
1985 account = tny_folder_get_account (folder);
1987 goto do_retrieve_frees;
1989 uncached_msgs = header_list_count_uncached_msgs (header_list);
1991 if (uncached_msgs > 0) {
1992 /* Allways download if we are online. */
1993 if (!tny_device_is_online (modest_runtime_get_device ())) {
1996 /* If ask for user permission to download the messages */
1997 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1998 ngettext("mcen_nc_get_msg",
2002 /* End if the user does not want to continue */
2003 if (response == GTK_RESPONSE_CANCEL)
2010 rf_helper = create_reply_forward_helper (action, win,
2011 reply_forward_type, header);
2012 if (uncached_msgs > 0) {
2013 modest_platform_connect_and_perform (GTK_WINDOW (win),
2015 reply_forward_performer,
2018 reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2019 account, rf_helper);
2024 g_object_unref (account);
2026 g_object_unref (folder);
2028 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
2031 g_object_unref (header_list);
2032 g_object_unref (header);
2037 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2039 g_return_if_fail (MODEST_IS_WINDOW(win));
2041 reply_forward (ACTION_REPLY, win);
2045 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2047 g_return_if_fail (MODEST_IS_WINDOW(win));
2049 reply_forward (ACTION_FORWARD, win);
2053 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2055 g_return_if_fail (MODEST_IS_WINDOW(win));
2057 reply_forward (ACTION_REPLY_TO_ALL, win);
2061 modest_ui_actions_on_next (GtkAction *action,
2062 ModestWindow *window)
2064 if (MODEST_IS_MAIN_WINDOW (window)) {
2065 GtkWidget *header_view;
2067 header_view = modest_main_window_get_child_widget (
2068 MODEST_MAIN_WINDOW(window),
2069 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2073 modest_header_view_select_next (
2074 MODEST_HEADER_VIEW(header_view));
2075 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2076 modest_msg_view_window_select_next_message (
2077 MODEST_MSG_VIEW_WINDOW (window));
2079 g_return_if_reached ();
2084 modest_ui_actions_on_prev (GtkAction *action,
2085 ModestWindow *window)
2087 g_return_if_fail (MODEST_IS_WINDOW(window));
2089 if (MODEST_IS_MAIN_WINDOW (window)) {
2090 GtkWidget *header_view;
2091 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2092 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2096 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2097 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2098 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2100 g_return_if_reached ();
2105 modest_ui_actions_on_sort (GtkAction *action,
2106 ModestWindow *window)
2108 GtkWidget *header_view = NULL;
2110 g_return_if_fail (MODEST_IS_WINDOW(window));
2112 if (MODEST_IS_MAIN_WINDOW (window)) {
2113 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2114 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2115 #ifdef MODEST_TOOLKIT_HILDON2
2116 } else if (MODEST_IS_HEADER_WINDOW (window)) {
2117 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2122 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2127 /* Show sorting dialog */
2128 modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2132 new_messages_arrived (ModestMailOperation *self,
2133 TnyList *new_headers,
2137 gboolean show_visual_notifications;
2139 source = modest_mail_operation_get_source (self);
2140 show_visual_notifications = (source) ? FALSE : TRUE;
2142 g_object_unref (source);
2144 /* Notify new messages have been downloaded. If the
2145 send&receive was invoked by the user then do not show any
2146 visual notification, only play a sound and activate the LED
2147 (for the Maemo version) */
2148 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2150 /* We only notify about really new messages (not seen) we get */
2151 TnyList *actually_new_list;
2152 TnyIterator *iterator;
2153 actually_new_list = TNY_LIST (tny_simple_list_new ());
2154 for (iterator = tny_list_create_iterator (new_headers);
2155 !tny_iterator_is_done (iterator);
2156 tny_iterator_next (iterator)) {
2158 TnyHeaderFlags flags;
2159 header = TNY_HEADER (tny_iterator_get_current (iterator));
2160 flags = tny_header_get_flags (header);
2162 if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2163 tny_list_append (actually_new_list, G_OBJECT (header));
2165 g_object_unref (header);
2167 g_object_unref (iterator);
2169 if (tny_list_get_length (actually_new_list) > 0) {
2170 GList *new_headers_list = NULL;
2172 new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2174 /* Send notifications */
2175 if (new_headers_list) {
2176 modest_platform_on_new_headers_received (new_headers_list,
2177 show_visual_notifications);
2179 modest_utils_free_notification_list (new_headers_list);
2182 g_object_unref (actually_new_list);
2188 retrieve_all_messages_cb (GObject *source,
2190 guint retrieve_limit)
2196 window = GTK_WINDOW (source);
2197 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2198 num_msgs, retrieve_limit);
2200 /* Ask the user if they want to retrieve all the messages */
2202 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2203 _("mcen_bd_get_all"),
2204 _("mcen_bd_newest_only"));
2205 /* Free and return */
2207 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2211 TnyAccount *account;
2213 gchar *account_name;
2214 gboolean poke_status;
2215 gboolean interactive;
2216 ModestMailOperation *mail_op;
2220 do_send_receive_performer (gboolean canceled,
2222 GtkWindow *parent_window,
2223 TnyAccount *account,
2226 SendReceiveInfo *info;
2228 info = (SendReceiveInfo *) user_data;
2230 if (err || canceled) {
2231 /* In disk full conditions we could get this error here */
2232 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2233 (GtkWidget *) parent_window, err,
2236 if (info->mail_op) {
2237 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2243 /* Set send/receive operation in progress */
2244 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2245 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2248 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2249 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2250 G_CALLBACK (on_send_receive_finished),
2253 /* Send & receive. */
2254 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2255 (info->win) ? retrieve_all_messages_cb : NULL,
2256 new_messages_arrived, info->win);
2261 g_object_unref (G_OBJECT (info->mail_op));
2262 if (info->account_name)
2263 g_free (info->account_name);
2265 g_object_unref (info->win);
2267 g_object_unref (info->account);
2268 g_slice_free (SendReceiveInfo, info);
2272 * This function performs the send & receive required actions. The
2273 * window is used to create the mail operation. Typically it should
2274 * always be the main window, but we pass it as argument in order to
2278 modest_ui_actions_do_send_receive (const gchar *account_name,
2279 gboolean force_connection,
2280 gboolean poke_status,
2281 gboolean interactive,
2284 gchar *acc_name = NULL;
2285 SendReceiveInfo *info;
2286 ModestTnyAccountStore *acc_store;
2287 TnyAccount *account;
2289 /* If no account name was provided then get the current account, and if
2290 there is no current account then pick the default one: */
2291 if (!account_name) {
2293 acc_name = g_strdup (modest_window_get_active_account (win));
2295 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2297 g_printerr ("modest: cannot get default account\n");
2301 acc_name = g_strdup (account_name);
2304 acc_store = modest_runtime_get_account_store ();
2305 account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2307 /* Do not automatically refresh accounts that are flagged as
2308 NO_AUTO_UPDATE. This could be useful for accounts that
2309 handle their own update times */
2311 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2312 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2313 const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2314 ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2316 if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2317 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2318 g_object_unref (account);
2325 /* Create the info for the connect and perform */
2326 info = g_slice_new (SendReceiveInfo);
2327 info->account_name = acc_name;
2328 info->win = (win) ? g_object_ref (win) : NULL;
2329 info->poke_status = poke_status;
2330 info->interactive = interactive;
2331 info->account = account;
2332 /* We need to create the operation here, because otherwise it
2333 could happen that the queue emits the queue-empty signal
2334 while we're trying to connect the account */
2335 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2336 modest_ui_actions_disk_operations_error_handler,
2338 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2340 /* Invoke the connect and perform */
2341 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2342 force_connection, info->account,
2343 do_send_receive_performer, info);
2348 modest_ui_actions_do_cancel_send (const gchar *account_name,
2351 TnyTransportAccount *transport_account;
2352 TnySendQueue *send_queue = NULL;
2353 GError *error = NULL;
2355 /* Get transport account */
2357 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2358 (modest_runtime_get_account_store(),
2360 TNY_ACCOUNT_TYPE_TRANSPORT));
2361 if (!transport_account) {
2362 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2367 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2368 if (!TNY_IS_SEND_QUEUE(send_queue)) {
2369 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2370 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2371 "modest: could not find send queue for account\n");
2373 /* Cancel the current send */
2374 tny_account_cancel (TNY_ACCOUNT (transport_account));
2376 /* Suspend all pending messages */
2377 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2381 if (transport_account != NULL)
2382 g_object_unref (G_OBJECT (transport_account));
2386 modest_ui_actions_cancel_send_all (ModestWindow *win)
2388 GSList *account_names, *iter;
2390 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2393 iter = account_names;
2395 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2396 iter = g_slist_next (iter);
2399 modest_account_mgr_free_account_names (account_names);
2400 account_names = NULL;
2404 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2407 /* Check if accounts exist */
2408 gboolean accounts_exist =
2409 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2411 /* If not, allow the user to create an account before trying to send/receive. */
2412 if (!accounts_exist)
2413 modest_ui_actions_on_accounts (NULL, win);
2415 /* Cancel all sending operaitons */
2416 modest_ui_actions_cancel_send_all (win);
2420 * Refreshes all accounts. This function will be used by automatic
2424 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2425 gboolean force_connection,
2426 gboolean poke_status,
2427 gboolean interactive)
2429 GSList *account_names, *iter;
2431 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2434 iter = account_names;
2436 modest_ui_actions_do_send_receive ((const char*) iter->data,
2438 poke_status, interactive, win);
2439 iter = g_slist_next (iter);
2442 modest_account_mgr_free_account_names (account_names);
2443 account_names = NULL;
2447 * Handler of the click on Send&Receive button in the main toolbar
2450 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2452 /* Check if accounts exist */
2453 gboolean accounts_exist;
2456 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2458 /* If not, allow the user to create an account before trying to send/receive. */
2459 if (!accounts_exist)
2460 modest_ui_actions_on_accounts (NULL, win);
2462 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2463 if (MODEST_IS_MAIN_WINDOW (win)) {
2464 GtkWidget *folder_view;
2465 TnyFolderStore *folder_store;
2468 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2469 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2473 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2476 g_object_unref (folder_store);
2477 /* Refresh the active account. Force the connection if needed
2478 and poke the status of all folders */
2479 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2480 #ifdef MODEST_TOOLKIT_HILDON2
2481 } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2482 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2485 const gchar *active_account;
2486 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2488 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2495 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2498 GtkWidget *header_view;
2500 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2502 header_view = modest_main_window_get_child_widget (main_window,
2503 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2507 conf = modest_runtime_get_conf ();
2509 /* what is saved/restored is depending on the style; thus; we save with
2510 * old style, then update the style, and restore for this new style
2512 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2514 if (modest_header_view_get_style
2515 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2516 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2517 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2519 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2520 MODEST_HEADER_VIEW_STYLE_DETAILS);
2522 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2523 MODEST_CONF_HEADER_VIEW_KEY);
2528 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2530 ModestMainWindow *main_window)
2532 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2533 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2535 /* in the case the folder is empty, show the empty folder message and focus
2537 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2538 if (modest_header_view_is_empty (header_view)) {
2539 TnyFolder *folder = modest_header_view_get_folder (header_view);
2540 GtkWidget *folder_view =
2541 modest_main_window_get_child_widget (main_window,
2542 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2543 if (folder != NULL) {
2544 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2545 g_object_unref (folder);
2547 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2551 /* If no header has been selected then exit */
2556 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2557 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2559 /* Update toolbar dimming state */
2560 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2561 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2565 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2568 ModestWindow *window)
2570 GtkWidget *open_widget;
2571 GtkTreeRowReference *rowref;
2573 g_return_if_fail (MODEST_IS_WINDOW(window));
2574 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2575 g_return_if_fail (TNY_IS_HEADER (header));
2577 if (modest_header_view_count_selected_headers (header_view) > 1) {
2578 /* Don't allow activation if there are more than one message selected */
2579 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2583 /* we check for low-mem; in that case, show a warning, and don't allow
2584 * activating headers
2586 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2589 if (MODEST_IS_MAIN_WINDOW (window)) {
2590 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2591 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2592 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2596 rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2597 open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2598 gtk_tree_row_reference_free (rowref);
2602 set_active_account_from_tny_account (TnyAccount *account,
2603 ModestWindow *window)
2605 const gchar *server_acc_name = tny_account_get_id (account);
2607 /* We need the TnyAccount provided by the
2608 account store because that is the one that
2609 knows the name of the Modest account */
2610 TnyAccount *modest_server_account =
2611 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2612 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2614 if (!modest_server_account) {
2615 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2619 /* Update active account, but only if it's not a pseudo-account */
2620 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2621 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2622 const gchar *modest_acc_name =
2623 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2624 if (modest_acc_name)
2625 modest_window_set_active_account (window, modest_acc_name);
2628 g_object_unref (modest_server_account);
2633 folder_refreshed_cb (ModestMailOperation *mail_op,
2637 ModestMainWindow *win = NULL;
2638 GtkWidget *folder_view, *header_view;
2639 const GError *error;
2641 g_return_if_fail (TNY_IS_FOLDER (folder));
2643 win = MODEST_MAIN_WINDOW (user_data);
2645 /* Check if the operation failed due to memory low conditions */
2646 error = modest_mail_operation_get_error (mail_op);
2647 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2648 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2649 modest_platform_run_information_dialog (GTK_WINDOW (win),
2650 _KR("memr_ib_operation_disabled"),
2656 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2658 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2661 TnyFolderStore *current_folder;
2663 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2664 if (current_folder) {
2665 gboolean different = ((TnyFolderStore *) folder != current_folder);
2666 g_object_unref (current_folder);
2672 /* Check if folder is empty and set headers view contents style */
2673 if ((tny_folder_get_all_count (folder) == 0) ||
2674 modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2675 modest_main_window_set_contents_style (win,
2676 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2680 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2681 TnyFolderStore *folder_store,
2683 ModestMainWindow *main_window)
2685 GtkWidget *header_view;
2687 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2689 header_view = modest_main_window_get_child_widget(main_window,
2690 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2695 if (TNY_IS_ACCOUNT (folder_store)) {
2697 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2699 /* Show account details */
2700 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2703 if (TNY_IS_FOLDER (folder_store) && selected) {
2704 TnyAccount *account;
2706 /* Update the active account */
2707 account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2709 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2710 g_object_unref (account);
2714 /* Set the header style by default, it could
2715 be changed later by the refresh callback to
2717 modest_main_window_set_contents_style (main_window,
2718 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2720 /* Set folder on header view. This function
2721 will call tny_folder_refresh_async so we
2722 pass a callback that will be called when
2723 finished. We use that callback to set the
2724 empty view if there are no messages */
2725 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2726 TNY_FOLDER (folder_store),
2728 MODEST_WINDOW (main_window),
2729 folder_refreshed_cb,
2732 /* Restore configuration. We need to do this
2733 *after* the set_folder because the widget
2734 memory asks the header view about its
2736 modest_widget_memory_restore (modest_runtime_get_conf (),
2737 G_OBJECT(header_view),
2738 MODEST_CONF_HEADER_VIEW_KEY);
2740 /* No need to save the header view
2741 configuration for Maemo because it only
2742 saves the sorting stuff and that it's
2743 already being done by the sort
2744 dialog. Remove it when the GNOME version
2745 has the same behaviour */
2746 #ifdef MODEST_TOOLKIT_GTK
2747 if (modest_main_window_get_contents_style (main_window) ==
2748 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2749 modest_widget_memory_save (modest_runtime_get_conf (),
2750 G_OBJECT (header_view),
2751 MODEST_CONF_HEADER_VIEW_KEY);
2753 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2757 /* Update dimming state */
2758 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2759 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2763 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2770 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2772 online = tny_device_is_online (modest_runtime_get_device());
2775 /* already online -- the item is simply not there... */
2776 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2778 GTK_MESSAGE_WARNING,
2780 _("The %s you selected cannot be found"),
2782 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2783 gtk_dialog_run (GTK_DIALOG(dialog));
2785 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2788 _("mcen_bd_dialog_cancel"),
2789 GTK_RESPONSE_REJECT,
2790 _("mcen_bd_dialog_ok"),
2791 GTK_RESPONSE_ACCEPT,
2793 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2794 "Do you want to get online?"), item);
2795 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2796 gtk_label_new (txt), FALSE, FALSE, 0);
2797 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2800 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2801 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2802 /* TODO: Comment about why is this commented out: */
2803 /* modest_platform_connect_and_wait (); */
2806 gtk_widget_destroy (dialog);
2810 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2813 /* g_debug ("%s %s", __FUNCTION__, link); */
2818 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2821 modest_platform_activate_uri (link);
2825 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2828 modest_platform_show_uri_popup (link);
2832 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2835 /* we check for low-mem; in that case, show a warning, and don't allow
2836 * viewing attachments
2838 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2841 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2845 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2846 const gchar *address,
2849 /* g_debug ("%s %s", __FUNCTION__, address); */
2853 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2854 TnyMsg *saved_draft,
2857 ModestMsgEditWindow *edit_window;
2859 /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2860 #ifndef MODEST_TOOLKIT_HILDON2
2861 ModestMainWindow *win;
2863 /* FIXME. Make the header view sensitive again. This is a
2864 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2866 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2867 modest_runtime_get_window_mgr(), FALSE));
2869 GtkWidget *hdrview = modest_main_window_get_child_widget(
2870 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2871 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2875 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2877 /* Set draft is there was no error */
2878 if (!modest_mail_operation_get_error (mail_op))
2879 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2881 g_object_unref(edit_window);
2885 enough_space_for_message (ModestMsgEditWindow *edit_window,
2888 guint64 available_disk, expected_size;
2893 available_disk = modest_utils_get_available_space (NULL);
2894 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2895 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2900 /* Double check: disk full condition or message too big */
2901 if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2902 expected_size > available_disk) {
2903 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2904 modest_platform_information_banner (NULL, NULL, msg);
2911 * djcb: if we're in low-memory state, we only allow for
2912 * saving messages smaller than
2913 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2914 * should still allow for sending anything critical...
2916 if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2917 modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2921 * djcb: we also make sure that the attachments are smaller than the max size
2922 * this is for the case where we'd try to forward a message with attachments
2923 * bigger than our max allowed size, or sending an message from drafts which
2924 * somehow got past our checks when attaching.
2926 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2927 modest_platform_run_information_dialog (
2928 GTK_WINDOW(edit_window),
2929 _FM("sfil_ib_opening_not_allowed"),
2938 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2940 TnyTransportAccount *transport_account;
2941 ModestMailOperation *mail_operation;
2943 gchar *account_name;
2944 ModestAccountMgr *account_mgr;
2945 gboolean had_error = FALSE;
2946 ModestMainWindow *win = NULL;
2948 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2950 data = modest_msg_edit_window_get_msg_data (edit_window);
2953 if (!enough_space_for_message (edit_window, data)) {
2954 modest_msg_edit_window_free_msg_data (edit_window, data);
2958 account_name = g_strdup (data->account_name);
2959 account_mgr = modest_runtime_get_account_mgr();
2961 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2963 account_name = modest_account_mgr_get_default_account (account_mgr);
2964 if (!account_name) {
2965 g_printerr ("modest: no account found\n");
2966 modest_msg_edit_window_free_msg_data (edit_window, data);
2970 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2971 account_name = g_strdup (data->account_name);
2975 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2976 (modest_runtime_get_account_store (),
2978 TNY_ACCOUNT_TYPE_TRANSPORT));
2979 if (!transport_account) {
2980 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2981 g_free (account_name);
2982 modest_msg_edit_window_free_msg_data (edit_window, data);
2986 /* Create the mail operation */
2987 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2989 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2991 modest_mail_operation_save_to_drafts (mail_operation,
3003 data->priority_flags,
3006 on_save_to_drafts_cb,
3007 g_object_ref(edit_window));
3009 #ifdef MODEST_TOOLKIT_HILDON2
3010 /* In hildon2 we always show the information banner on saving to drafts.
3011 * It will be a system information banner in this case.
3013 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3014 modest_platform_information_banner (NULL, NULL, text);
3017 /* Use the main window as the parent of the banner, if the
3018 main window does not exist it won't be shown, if the parent
3019 window exists then it's properly shown. We don't use the
3020 editor window because it could be closed (save to drafts
3021 could happen after closing the window */
3022 win = (ModestMainWindow *)
3023 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3025 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3026 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3030 modest_msg_edit_window_set_modified (edit_window, FALSE);
3033 g_free (account_name);
3034 g_object_unref (G_OBJECT (transport_account));
3035 g_object_unref (G_OBJECT (mail_operation));
3037 modest_msg_edit_window_free_msg_data (edit_window, data);
3040 * If the drafts folder is selected then make the header view
3041 * insensitive while the message is being saved to drafts
3042 * (it'll be sensitive again in on_save_to_drafts_cb()). This
3043 * is not very clean but it avoids letting the drafts folder
3044 * in an inconsistent state: the user could edit the message
3045 * being saved and undesirable things would happen.
3046 * In the average case the user won't notice anything at
3047 * all. In the worst case (the user is editing a really big
3048 * file from Drafts) the header view will be insensitive
3049 * during the saving process (10 or 20 seconds, depending on
3050 * the message). Anyway this is just a quick workaround: once
3051 * we find a better solution it should be removed
3052 * See NB#65125 (commend #18) for details.
3054 if (!had_error && win != NULL) {
3055 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3056 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3058 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3060 if (modest_tny_folder_is_local_folder(folder)) {
3061 TnyFolderType folder_type;
3062 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3063 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3064 GtkWidget *hdrview = modest_main_window_get_child_widget(
3065 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3066 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3070 if (folder != NULL) g_object_unref(folder);
3077 /* For instance, when clicking the Send toolbar button when editing a message: */
3079 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3081 TnyTransportAccount *transport_account = NULL;
3082 gboolean had_error = FALSE;
3084 ModestAccountMgr *account_mgr;
3085 gchar *account_name;
3086 ModestMailOperation *mail_operation;
3089 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3091 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3094 data = modest_msg_edit_window_get_msg_data (edit_window);
3096 if (data->subject == NULL || data->subject[0] == '\0') {
3097 /* Empty subject -> no send */
3098 modest_msg_edit_window_free_msg_data (edit_window, data);
3102 recipients = g_strconcat (data->to?data->to:"",
3103 data->cc?data->cc:"",
3104 data->bcc?data->bcc:"",
3106 if (recipients == NULL || recipients[0] == '\0') {
3107 /* Empty subject -> no send */
3108 g_free (recipients);
3109 modest_msg_edit_window_free_msg_data (edit_window, data);
3112 g_free (recipients);
3115 if (!enough_space_for_message (edit_window, data)) {
3116 modest_msg_edit_window_free_msg_data (edit_window, data);
3120 account_mgr = modest_runtime_get_account_mgr();
3121 account_name = g_strdup (data->account_name);
3123 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3126 account_name = modest_account_mgr_get_default_account (account_mgr);
3128 if (!account_name) {
3129 modest_msg_edit_window_free_msg_data (edit_window, data);
3130 /* Run account setup wizard */
3131 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3136 /* Get the currently-active transport account for this modest account: */
3137 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3139 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3140 (modest_runtime_get_account_store (),
3141 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3144 if (!transport_account) {
3145 modest_msg_edit_window_free_msg_data (edit_window, data);
3146 /* Run account setup wizard */
3147 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3152 /* Create the mail operation */
3153 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3154 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3156 modest_mail_operation_send_new_mail (mail_operation,
3170 data->priority_flags);
3172 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3173 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3175 if (modest_mail_operation_get_error (mail_operation) != NULL) {
3176 const GError *error = modest_mail_operation_get_error (mail_operation);
3177 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3178 error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3179 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3180 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3186 g_free (account_name);
3187 g_object_unref (G_OBJECT (transport_account));
3188 g_object_unref (G_OBJECT (mail_operation));
3190 modest_msg_edit_window_free_msg_data (edit_window, data);
3193 modest_msg_edit_window_set_sent (edit_window, TRUE);
3195 /* Save settings and close the window: */
3196 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3203 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3204 ModestMsgEditWindow *window)
3206 ModestMsgEditFormatState *format_state = NULL;
3208 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3209 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3211 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3214 format_state = modest_msg_edit_window_get_format_state (window);
3215 g_return_if_fail (format_state != NULL);
3217 format_state->bold = gtk_toggle_action_get_active (action);
3218 modest_msg_edit_window_set_format_state (window, format_state);
3219 g_free (format_state);
3224 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3225 ModestMsgEditWindow *window)
3227 ModestMsgEditFormatState *format_state = NULL;
3229 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3230 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3232 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3235 format_state = modest_msg_edit_window_get_format_state (window);
3236 g_return_if_fail (format_state != NULL);
3238 format_state->italics = gtk_toggle_action_get_active (action);
3239 modest_msg_edit_window_set_format_state (window, format_state);
3240 g_free (format_state);
3245 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3246 ModestMsgEditWindow *window)
3248 ModestMsgEditFormatState *format_state = NULL;
3250 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3251 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3253 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3256 format_state = modest_msg_edit_window_get_format_state (window);
3257 g_return_if_fail (format_state != NULL);
3259 format_state->bullet = gtk_toggle_action_get_active (action);
3260 modest_msg_edit_window_set_format_state (window, format_state);
3261 g_free (format_state);
3266 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3267 GtkRadioAction *selected,
3268 ModestMsgEditWindow *window)
3270 ModestMsgEditFormatState *format_state = NULL;
3271 GtkJustification value;
3273 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3275 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3278 value = gtk_radio_action_get_current_value (selected);
3280 format_state = modest_msg_edit_window_get_format_state (window);
3281 g_return_if_fail (format_state != NULL);
3283 format_state->justification = value;
3284 modest_msg_edit_window_set_format_state (window, format_state);
3285 g_free (format_state);
3289 modest_ui_actions_on_select_editor_color (GtkAction *action,
3290 ModestMsgEditWindow *window)
3292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293 g_return_if_fail (GTK_IS_ACTION (action));
3295 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3298 modest_msg_edit_window_select_color (window);
3302 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3303 ModestMsgEditWindow *window)
3305 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3306 g_return_if_fail (GTK_IS_ACTION (action));
3308 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3311 modest_msg_edit_window_select_background_color (window);
3315 modest_ui_actions_on_insert_image (GObject *object,
3316 ModestMsgEditWindow *window)
3318 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3321 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3324 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3327 modest_msg_edit_window_insert_image (window);
3331 modest_ui_actions_on_attach_file (GtkAction *action,
3332 ModestMsgEditWindow *window)
3334 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3335 g_return_if_fail (GTK_IS_ACTION (action));
3337 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3340 modest_msg_edit_window_offer_attach_file (window);
3344 modest_ui_actions_on_remove_attachments (GtkAction *action,
3345 ModestMsgEditWindow *window)
3347 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3349 modest_msg_edit_window_remove_attachments (window, NULL);
3353 do_create_folder_cb (ModestMailOperation *mail_op,
3354 TnyFolderStore *parent_folder,
3355 TnyFolder *new_folder,
3358 gchar *suggested_name = (gchar *) user_data;
3359 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3360 const GError *error;
3362 error = modest_mail_operation_get_error (mail_op);
3365 TnyAccount *account;
3366 /* Show an error. If there was some problem writing to
3367 disk, show it, otherwise show the generic folder
3368 create error. We do it here and not in an error
3369 handler because the call to do_create_folder will
3370 stop the main loop in a gtk_dialog_run and then,
3371 the message won't be shown until that dialog is
3373 account = modest_mail_operation_get_account (mail_op);
3376 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3377 (GtkWidget *) source_win,
3380 _("mail_in_ui_folder_create_error_memory"));
3381 g_object_unref (account);
3384 /* Show an error and try again if there is no
3385 full memory condition */
3386 modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3387 _("mail_in_ui_folder_create_error"));
3388 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3392 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3393 * FIXME: any other? */
3394 GtkWidget *folder_view;
3396 if (MODEST_IS_MAIN_WINDOW(source_win))
3398 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3399 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3401 folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3402 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3404 /* Select the newly created folder. It could happen
3405 that the widget is no longer there (i.e. the window
3406 has been destroyed, so we need to check this */
3408 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3410 g_object_unref (new_folder);
3412 /* Free. Note that the first time it'll be NULL so noop */
3413 g_free (suggested_name);
3414 g_object_unref (source_win);
3419 TnyFolderStore *parent;
3420 } CreateFolderConnect;
3423 do_create_folder_performer (gboolean canceled,
3425 GtkWindow *parent_window,
3426 TnyAccount *account,
3429 CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3430 ModestMailOperation *mail_op;
3432 if (canceled || err) {
3433 TnyAccount *account = modest_mail_operation_get_account (mail_op);
3434 /* In disk full conditions we could get this error here */
3435 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3436 (GtkWidget *) parent_window, err,
3438 _("mail_in_ui_folder_create_error_memory"));
3440 g_object_unref (account);
3442 /* This happens if we have selected the outbox folder
3444 if (err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3445 TNY_IS_MERGE_FOLDER (helper->parent)) {
3446 /* Show an error and retry */
3447 modest_platform_information_banner ((GtkWidget *) parent_window,
3449 _("mail_in_ui_folder_create_error"));
3451 do_create_folder (parent_window, helper->parent, helper->folder_name);
3457 mail_op = modest_mail_operation_new ((GObject *) parent_window);
3458 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3460 modest_mail_operation_create_folder (mail_op,
3462 (const gchar *) helper->folder_name,
3463 do_create_folder_cb,
3464 g_strdup (helper->folder_name));
3465 g_object_unref (mail_op);
3469 g_object_unref (helper->parent);
3470 if (helper->folder_name)
3471 g_free (helper->folder_name);
3472 g_slice_free (CreateFolderConnect, helper);
3477 do_create_folder (GtkWindow *parent_window,
3478 TnyFolderStore *suggested_parent,
3479 const gchar *suggested_name)
3482 gchar *folder_name = NULL;
3483 TnyFolderStore *parent_folder = NULL;
3485 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3487 (gchar *) suggested_name,
3491 if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3492 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3493 helper->folder_name = g_strdup (folder_name);
3494 helper->parent = g_object_ref (parent_folder);
3496 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3499 do_create_folder_performer,
3504 g_free (folder_name);
3506 g_object_unref (parent_folder);
3510 modest_ui_actions_create_folder(GtkWidget *parent_window,
3511 GtkWidget *folder_view,
3512 TnyFolderStore *parent_folder)
3514 if (!parent_folder) {
3515 #ifdef MODEST_TOOLKIT_HILDON2
3516 ModestTnyAccountStore *acc_store;
3518 acc_store = modest_runtime_get_account_store ();
3520 parent_folder = (TnyFolderStore *)
3521 modest_tny_account_store_get_local_folders_account (acc_store);
3523 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3527 if (parent_folder) {
3528 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3529 g_object_unref (parent_folder);
3534 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3537 g_return_if_fail (MODEST_IS_WINDOW(window));
3539 if (MODEST_IS_MAIN_WINDOW (window)) {
3540 GtkWidget *folder_view;
3542 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3543 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3547 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3548 #ifdef MODEST_TOOLKIT_HILDON2
3549 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3550 GtkWidget *folder_view;
3552 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3553 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3556 g_assert_not_reached ();
3561 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3564 const GError *error = NULL;
3565 gchar *message = NULL;
3567 TnyAccount *account = modest_mail_operation_get_account (mail_op);
3569 /* Get error message */
3570 error = modest_mail_operation_get_error (mail_op);
3572 g_return_if_reached ();
3574 mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3575 (GError *) error, account);
3577 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3578 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3579 error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3580 message = _CS("ckdg_ib_folder_already_exists");
3581 } else if (error->domain == TNY_ERROR_DOMAIN &&
3582 error->code == TNY_SERVICE_ERROR_STATE) {
3583 /* This means that the folder is already in use (a
3584 message is opened for example */
3585 message = _("emev_ni_internal_error");
3587 message = _CS("ckdg_ib_unable_to_rename");
3590 /* We don't set a parent for the dialog because the dialog
3591 will be destroyed so the banner won't appear */
3592 modest_platform_information_banner (NULL, NULL, message);
3595 g_object_unref (account);
3601 TnyFolderStore *folder;
3606 on_rename_folder_cb (ModestMailOperation *mail_op,
3607 TnyFolder *new_folder,
3610 ModestFolderView *folder_view;
3612 /* If the window was closed when renaming a folder, or if
3613 * it's not a main window this will happen */
3614 if (!MODEST_IS_FOLDER_VIEW (user_data))
3617 folder_view = MODEST_FOLDER_VIEW (user_data);
3618 /* Note that if the rename fails new_folder will be NULL */
3620 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3622 modest_folder_view_select_first_inbox_or_local (folder_view);
3624 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3628 on_rename_folder_performer (gboolean canceled,
3630 GtkWindow *parent_window,
3631 TnyAccount *account,
3634 ModestMailOperation *mail_op = NULL;
3635 GtkTreeSelection *sel = NULL;
3636 GtkWidget *folder_view = NULL;
3637 RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3639 if (canceled || err) {
3640 /* In disk full conditions we could get this error here */
3641 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3642 (GtkWidget *) parent_window, err,
3647 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3648 modest_ui_actions_rename_folder_error_handler,
3649 parent_window, NULL);
3651 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3654 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3656 folder_view = modest_main_window_get_child_widget (
3657 MODEST_MAIN_WINDOW (parent_window),
3658 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3660 #ifdef MODEST_TOOLKIT_HILDON2
3661 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3662 ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3663 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3667 /* Clear the folders view */
3668 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3669 gtk_tree_selection_unselect_all (sel);
3671 /* Actually rename the folder */
3672 modest_mail_operation_rename_folder (mail_op,
3673 TNY_FOLDER (data->folder),
3674 (const gchar *) (data->new_name),
3675 on_rename_folder_cb,
3677 g_object_unref (mail_op);
3680 g_object_unref (data->folder);
3681 g_free (data->new_name);
3686 modest_ui_actions_on_rename_folder (GtkAction *action,
3687 ModestWindow *window)
3689 modest_ui_actions_on_edit_mode_rename_folder (window);
3693 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3695 TnyFolderStore *folder;
3696 GtkWidget *folder_view;
3697 gboolean do_rename = TRUE;
3699 g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3701 if (MODEST_IS_MAIN_WINDOW (window)) {
3702 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3703 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3707 #ifdef MODEST_TOOLKIT_HILDON2
3708 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3709 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3715 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3720 if (TNY_IS_FOLDER (folder)) {
3721 gchar *folder_name = NULL;
3723 const gchar *current_name;
3724 TnyFolderStore *parent;
3726 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3727 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3728 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3729 parent, current_name,
3731 g_object_unref (parent);
3733 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3736 RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3737 rename_folder_data->folder = g_object_ref (folder);
3738 rename_folder_data->new_name = folder_name;
3739 modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3740 folder, on_rename_folder_performer, rename_folder_data);
3743 g_object_unref (folder);
3748 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3751 GObject *win = modest_mail_operation_get_source (mail_op);
3753 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,