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-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46 #include "modest-debug.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51 #ifdef MODEST_TOOLKIT_HILDON2
52 #include <modest-accounts-window.h>
53 #include <hildon/hildon-pannable-area.h>
54 #include <hildon/hildon-gtk.h>
55 #include <modest-header-window.h>
58 #ifdef MODEST_PLATFORM_MAEMO
59 #include "maemo/modest-osso-state-saving.h"
60 #endif /* MODEST_PLATFORM_MAEMO */
61 #ifndef MODEST_TOOLKIT_GTK
62 #include "maemo/modest-hildon-includes.h"
63 #include "maemo/modest-connection-specific-smtp-window.h"
64 #endif /* !MODEST_TOOLKIT_GTK */
65 #include <modest-utils.h>
67 #include "widgets/modest-ui-constants.h"
68 #include <widgets/modest-main-window.h>
69 #include <widgets/modest-msg-view-window.h>
70 #include <widgets/modest-account-view-window.h>
71 #include <widgets/modest-details-dialog.h>
72 #include <widgets/modest-attachments-view.h>
73 #include "widgets/modest-folder-view.h"
74 #include "widgets/modest-global-settings-dialog.h"
75 #include "modest-account-mgr-helpers.h"
76 #include "modest-mail-operation.h"
77 #include "modest-text-utils.h"
78 #include <modest-widget-memory.h>
79 #include <tny-error.h>
80 #include <tny-simple-list.h>
81 #include <tny-msg-view.h>
82 #include <tny-device.h>
83 #include <tny-merge-folder.h>
85 #include <gtkhtml/gtkhtml.h>
87 #define MIN_FREE_SPACE 5 * 1024 * 1024
88 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
90 typedef struct _GetMsgAsyncHelper {
92 ModestMailOperation *mail_op;
99 typedef enum _ReplyForwardAction {
103 } ReplyForwardAction;
105 typedef struct _ReplyForwardHelper {
106 guint reply_forward_type;
107 ReplyForwardAction action;
109 GtkWidget *parent_window;
111 } ReplyForwardHelper;
113 typedef struct _MoveToHelper {
114 GtkTreeRowReference *reference;
118 typedef struct _PasteAsAttachmentHelper {
119 ModestMsgEditWindow *window;
121 } PasteAsAttachmentHelper;
129 * The do_headers_action uses this kind of functions to perform some
130 * action to each member of a list of headers
132 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
134 static void do_headers_action (ModestWindow *win,
138 static void open_msg_cb (ModestMailOperation *mail_op,
145 static void reply_forward_cb (ModestMailOperation *mail_op,
152 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
154 static void folder_refreshed_cb (ModestMailOperation *mail_op,
158 static void on_send_receive_finished (ModestMailOperation *mail_op,
161 static gint header_list_count_uncached_msgs (TnyList *header_list);
163 static gboolean connect_to_get_msg (ModestWindow *win,
164 gint num_of_uncached_msgs,
165 TnyAccount *account);
167 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
169 static void do_create_folder (GtkWindow *window,
170 TnyFolderStore *parent_folder,
171 const gchar *suggested_name);
173 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
175 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
176 GtkWidget *folder_view,
177 TnyFolderStore *dst_folder,
178 ModestMainWindow *win);
180 static void modest_ui_actions_on_window_move_to (GtkAction *action,
181 TnyList *list_to_move,
182 TnyFolderStore *dst_folder,
186 * This function checks whether a TnyFolderStore is a pop account
189 remote_folder_has_leave_on_server (TnyFolderStore *folder)
194 g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
196 account = get_account_from_folder_store (folder);
197 result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
198 modest_tny_account_get_protocol_type (account)));
199 g_object_unref (account);
204 /* FIXME: this should be merged with the similar code in modest-account-view-window */
205 /* Show the account creation wizard dialog.
206 * returns: TRUE if an account was created. FALSE if the user cancelled.
209 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
211 gboolean result = FALSE;
213 gint dialog_response;
215 /* there is no such wizard yet */
216 wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
217 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
219 /* always present a main window in the background
220 * we do it here, so we cannot end up with two wizards (as this
221 * function might be called in modest_window_mgr_get_main_window as well */
223 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
224 TRUE); /* create if not existent */
226 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
228 /* make sure the mainwindow is visible. We need to present the
229 wizard again to give it the focus back. show_all are needed
230 in order to get the widgets properly drawn (MainWindow main
231 paned won't be in its right position and the dialog will be
233 #ifndef MODEST_TOOLKIT_HILDON2
234 gtk_widget_show_all (GTK_WIDGET (win));
235 gtk_widget_show_all (GTK_WIDGET (wizard));
236 gtk_window_present (GTK_WINDOW (win));
237 gtk_window_present (GTK_WINDOW (wizard));
240 dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
241 gtk_widget_destroy (GTK_WIDGET (wizard));
242 if (gtk_events_pending ())
243 gtk_main_iteration ();
245 if (dialog_response == GTK_RESPONSE_CANCEL) {
248 /* Check whether an account was created: */
249 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
256 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
259 const gchar *authors[] = {
260 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
263 about = gtk_about_dialog_new ();
264 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
265 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
266 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
267 _("Copyright (c) 2006, Nokia Corporation\n"
268 "All rights reserved."));
269 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
270 _("a modest e-mail client\n\n"
271 "design and implementation: Dirk-Jan C. Binnema\n"
272 "contributions from the fine people at KC and Ig\n"
273 "uses the tinymail email framework written by Philip van Hoof"));
274 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
275 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
276 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
277 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
279 gtk_dialog_run (GTK_DIALOG (about));
280 gtk_widget_destroy(about);
284 * Gets the list of currently selected messages. If the win is the
285 * main window, then it returns a newly allocated list of the headers
286 * selected in the header view. If win is the msg view window, then
287 * the value returned is a list with just a single header.
289 * The caller of this funcion must free the list.
292 get_selected_headers (ModestWindow *win)
294 if (MODEST_IS_MAIN_WINDOW(win)) {
295 GtkWidget *header_view;
297 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
298 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
299 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
301 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
302 /* for MsgViewWindows, we simply return a list with one element */
304 TnyList *list = NULL;
306 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
307 if (header != NULL) {
308 list = tny_simple_list_new ();
309 tny_list_prepend (list, G_OBJECT(header));
310 g_object_unref (G_OBJECT(header));
315 #ifdef MODEST_TOOLKIT_HILDON2
316 } else if (MODEST_IS_HEADER_WINDOW (win)) {
317 GtkWidget *header_view;
319 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
320 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
326 static GtkTreeRowReference *
327 get_next_after_selected_headers (ModestHeaderView *header_view)
329 GtkTreeSelection *sel;
330 GList *selected_rows, *node;
332 GtkTreeRowReference *result;
335 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
336 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
337 selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
339 if (selected_rows == NULL)
342 node = g_list_last (selected_rows);
343 path = gtk_tree_path_copy ((GtkTreePath *) node->data);
344 gtk_tree_path_next (path);
346 result = gtk_tree_row_reference_new (model, path);
348 gtk_tree_path_free (path);
349 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
350 g_list_free (selected_rows);
356 headers_action_mark_as_read (TnyHeader *header,
360 TnyHeaderFlags flags;
362 g_return_if_fail (TNY_IS_HEADER(header));
364 flags = tny_header_get_flags (header);
365 if (flags & TNY_HEADER_FLAG_SEEN) return;
366 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
370 headers_action_mark_as_unread (TnyHeader *header,
374 TnyHeaderFlags flags;
376 g_return_if_fail (TNY_IS_HEADER(header));
378 flags = tny_header_get_flags (header);
379 if (flags & TNY_HEADER_FLAG_SEEN) {
380 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
384 /** After deleing a message that is currently visible in a window,
385 * show the next message from the list, or close the window if there are no more messages.
388 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
390 /* Close msg view window or select next */
391 if (!modest_msg_view_window_select_next_message (win) &&
392 !modest_msg_view_window_select_previous_message (win)) {
394 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
400 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
402 modest_ui_actions_on_edit_mode_delete_message (win);
406 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
408 TnyList *header_list = NULL;
409 TnyIterator *iter = NULL;
410 TnyHeader *header = NULL;
411 gchar *message = NULL;
414 ModestWindowMgr *mgr;
415 GtkWidget *header_view = NULL;
416 gboolean retval = TRUE;
418 g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
420 /* Check first if the header view has the focus */
421 if (MODEST_IS_MAIN_WINDOW (win)) {
423 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
424 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
425 if (!gtk_widget_is_focus (header_view))
429 /* Get the headers, either from the header view (if win is the main window),
430 * or from the message view window: */
431 header_list = get_selected_headers (win);
432 if (!header_list) return FALSE;
434 /* Check if any of the headers are already opened, or in the process of being opened */
435 if (MODEST_IS_MAIN_WINDOW (win)) {
436 gint opened_headers = 0;
438 iter = tny_list_create_iterator (header_list);
439 mgr = modest_runtime_get_window_mgr ();
440 while (!tny_iterator_is_done (iter)) {
441 header = TNY_HEADER (tny_iterator_get_current (iter));
443 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
445 g_object_unref (header);
447 tny_iterator_next (iter);
449 g_object_unref (iter);
451 if (opened_headers > 0) {
454 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
457 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
460 g_object_unref (header_list);
466 if (tny_list_get_length(header_list) == 1) {
467 iter = tny_list_create_iterator (header_list);
468 header = TNY_HEADER (tny_iterator_get_current (iter));
471 subject = tny_header_dup_subject (header);
473 subject = g_strdup (_("mail_va_no_subject"));
474 desc = g_strdup_printf ("%s", subject);
476 g_object_unref (header);
479 g_object_unref (iter);
481 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
482 tny_list_get_length(header_list)), desc);
484 /* Confirmation dialog */
485 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
489 if (response == GTK_RESPONSE_OK) {
490 ModestWindow *main_window = NULL;
491 ModestWindowMgr *mgr = NULL;
492 GtkTreeModel *model = NULL;
493 GtkTreeSelection *sel = NULL;
494 GList *sel_list = NULL, *tmp = NULL;
495 GtkTreeRowReference *next_row_reference = NULL;
496 GtkTreeRowReference *prev_row_reference = NULL;
497 GtkTreePath *next_path = NULL;
498 GtkTreePath *prev_path = NULL;
499 ModestMailOperation *mail_op = NULL;
501 /* Find last selected row */
502 if (MODEST_IS_MAIN_WINDOW (win)) {
503 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
504 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
505 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
506 for (tmp=sel_list; tmp; tmp=tmp->next) {
507 if (tmp->next == NULL) {
508 prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
509 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
511 gtk_tree_path_prev (prev_path);
512 gtk_tree_path_next (next_path);
514 prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
515 next_row_reference = gtk_tree_row_reference_new (model, next_path);
520 /* Disable window dimming management */
521 modest_window_disable_dimming (MODEST_WINDOW(win));
523 /* Remove each header. If it's a view window header_view == NULL */
524 mail_op = modest_mail_operation_new ((GObject *) win);
525 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
527 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
528 g_object_unref (mail_op);
530 /* Enable window dimming management */
532 gtk_tree_selection_unselect_all (sel);
534 modest_window_enable_dimming (MODEST_WINDOW(win));
536 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
537 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
539 /* Get main window */
540 mgr = modest_runtime_get_window_mgr ();
541 main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
542 } else if (MODEST_IS_MAIN_WINDOW (win)) {
543 /* Move cursor to next row */
546 /* Select next or previous row */
547 if (gtk_tree_row_reference_valid (next_row_reference)) {
548 gtk_tree_selection_select_path (sel, next_path);
550 else if (gtk_tree_row_reference_valid (prev_row_reference)) {
551 gtk_tree_selection_select_path (sel, prev_path);
555 if (gtk_tree_row_reference_valid (next_row_reference))
556 gtk_tree_row_reference_free (next_row_reference);
557 if (next_path != NULL)
558 gtk_tree_path_free (next_path);
559 if (gtk_tree_row_reference_valid (prev_row_reference))
560 gtk_tree_row_reference_free (prev_row_reference);
561 if (prev_path != NULL)
562 gtk_tree_path_free (prev_path);
565 /* Update toolbar dimming state */
567 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
568 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
572 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
573 g_list_free (sel_list);
582 g_object_unref (header_list);
590 /* delete either message or folder, based on where we are */
592 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
594 g_return_if_fail (MODEST_IS_WINDOW(win));
596 /* Check first if the header view has the focus */
597 if (MODEST_IS_MAIN_WINDOW (win)) {
599 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
600 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
601 if (gtk_widget_is_focus (w)) {
602 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
606 modest_ui_actions_on_delete_message (action, win);
610 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
612 ModestWindowMgr *mgr = NULL;
614 #ifdef MODEST_PLATFORM_MAEMO
615 modest_osso_save_state();
616 #endif /* MODEST_PLATFORM_MAEMO */
618 g_debug ("closing down, clearing %d item(s) from operation queue",
619 modest_mail_operation_queue_num_elements
620 (modest_runtime_get_mail_operation_queue()));
622 /* cancel all outstanding operations */
623 modest_mail_operation_queue_cancel_all
624 (modest_runtime_get_mail_operation_queue());
626 g_debug ("queue has been cleared");
629 /* Check if there are opened editing windows */
630 mgr = modest_runtime_get_window_mgr ();
631 modest_window_mgr_close_all_windows (mgr);
633 /* note: when modest-tny-account-store is finalized,
634 it will automatically set all network connections
637 /* gtk_main_quit (); */
641 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
645 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
647 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
648 /* gtk_widget_destroy (GTK_WIDGET (win)); */
649 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
650 /* gboolean ret_value; */
651 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
652 /* } else if (MODEST_IS_WINDOW (win)) { */
653 /* gtk_widget_destroy (GTK_WIDGET (win)); */
655 /* g_return_if_reached (); */
660 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
662 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
664 modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
668 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
670 GtkClipboard *clipboard = NULL;
671 gchar *selection = NULL;
673 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
674 selection = gtk_clipboard_wait_for_text (clipboard);
676 /* Question: why is the clipboard being used here?
677 * It doesn't really make a lot of sense. */
681 modest_address_book_add_address (selection);
687 modest_ui_actions_on_accounts (GtkAction *action,
690 /* This is currently only implemented for Maemo */
691 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
692 if (!modest_ui_actions_run_account_setup_wizard (win))
693 g_debug ("%s: wizard was already running", __FUNCTION__);
697 /* Show the list of accounts */
698 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
700 /* The accounts dialog must be modal */
701 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
702 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
707 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
709 /* This is currently only implemented for Maemo,
710 * because it requires an API (libconic) to detect different connection
713 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
715 /* Create the window if necessary: */
716 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
717 modest_connection_specific_smtp_window_fill_with_connections (
718 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
719 modest_runtime_get_account_mgr());
721 /* Show the window: */
722 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
723 GTK_WINDOW (specific_window), (GtkWindow *) win);
724 gtk_widget_show (specific_window);
725 #endif /* !MODEST_TOOLKIT_GTK */
729 modest_ui_actions_compose_msg(ModestWindow *win,
732 const gchar *bcc_str,
733 const gchar *subject_str,
734 const gchar *body_str,
736 gboolean set_as_modified)
738 gchar *account_name = NULL;
740 TnyAccount *account = NULL;
741 TnyFolder *folder = NULL;
742 gchar *from_str = NULL, *signature = NULL, *body = NULL;
743 gboolean use_signature = FALSE;
744 ModestWindow *msg_win = NULL;
745 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
746 ModestTnyAccountStore *store = modest_runtime_get_account_store();
747 GnomeVFSFileSize total_size, allowed_size;
749 /* we check for low-mem */
750 if (modest_platform_check_memory_low (win, TRUE))
753 #ifdef MODEST_TOOLKIT_HILDON2
754 account_name = g_strdup (modest_window_get_active_account(win));
757 account_name = modest_account_mgr_get_default_account(mgr);
760 g_printerr ("modest: no account found\n");
763 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
765 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
768 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
770 g_printerr ("modest: failed to find Drafts folder\n");
773 from_str = modest_account_mgr_get_from_string (mgr, account_name);
775 g_printerr ("modest: failed get from string for '%s'\n", account_name);
779 signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
780 if (body_str != NULL) {
781 body = use_signature ? g_strconcat(body_str, "\n--\n", signature, NULL) : g_strdup(body_str);
783 body = use_signature ? g_strconcat("\n--\n", signature, NULL) : g_strdup("");
786 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL, NULL, NULL);
788 g_printerr ("modest: failed to create new msg\n");
792 /* Create and register edit window */
793 /* This is destroyed by TODO. */
795 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
796 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
798 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
799 gtk_widget_destroy (GTK_WIDGET (msg_win));
802 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
803 gtk_widget_show_all (GTK_WIDGET (msg_win));
805 while (attachments) {
807 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
808 attachments->data, allowed_size);
810 if (total_size > allowed_size) {
811 g_warning ("%s: total size: %u",
812 __FUNCTION__, (unsigned int)total_size);
815 allowed_size -= total_size;
817 attachments = g_slist_next(attachments);
824 g_free (account_name);
826 g_object_unref (G_OBJECT(account));
828 g_object_unref (G_OBJECT(folder));
830 g_object_unref (G_OBJECT(msg));
834 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
836 /* if there are no accounts yet, just show the wizard */
837 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
838 if (!modest_ui_actions_run_account_setup_wizard (win))
841 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
846 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
850 ModestMailOperationStatus status;
852 /* If there is no message or the operation was not successful */
853 status = modest_mail_operation_get_status (mail_op);
854 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
857 /* If it's a memory low issue, then show a banner */
858 error = modest_mail_operation_get_error (mail_op);
859 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
860 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
861 GObject *source = modest_mail_operation_get_source (mail_op);
862 modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
863 dgettext("ke-recv","memr_ib_operation_disabled"),
865 g_object_unref (source);
868 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
869 error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
870 gchar *subject, *msg;
871 subject = tny_header_dup_subject (header);
873 subject = g_strdup (_("mail_va_no_subject"));;
874 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
876 modest_platform_run_information_dialog (NULL, msg, FALSE);
881 /* Remove the header from the preregistered uids */
882 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
900 OpenMsgBannerInfo *banner_info;
901 GtkTreeRowReference *rowref;
905 open_msg_banner_idle (gpointer userdata)
907 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
909 gdk_threads_enter ();
910 banner_info->idle_handler = 0;
911 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
913 g_object_ref (banner_info->banner);
915 gdk_threads_leave ();
922 get_header_view_from_window (ModestWindow *window)
924 GtkWidget *header_view;
926 if (MODEST_IS_MAIN_WINDOW (window)) {
927 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
928 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
929 #ifdef MODEST_TOOLKIT_HILDON2
930 } else if (MODEST_IS_HEADER_WINDOW (window)){
931 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
941 get_info_from_header (TnyHeader *header, gboolean *is_draft)
944 gchar *account = NULL;
945 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
949 folder = tny_header_get_folder (header);
950 /* Gets folder type (OUTBOX headers will be opened in edit window */
951 if (modest_tny_folder_is_local_folder (folder)) {
952 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
953 if (folder_type == TNY_FOLDER_TYPE_INVALID)
954 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
957 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
958 TnyTransportAccount *traccount = NULL;
959 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
960 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
962 ModestTnySendQueue *send_queue = NULL;
963 ModestTnySendQueueStatus status;
965 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
966 TNY_ACCOUNT(traccount)));
967 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
968 if (TNY_IS_SEND_QUEUE (send_queue)) {
969 msg_id = modest_tny_send_queue_get_msg_id (header);
970 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
972 /* Only open messages in outbox with the editor if they are in Failed state */
973 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
976 #ifdef MODEST_TOOLKIT_HILDON2
978 /* In Fremantle we can not
979 open any message from
980 outbox which is not in
982 g_object_unref(traccount);
986 g_object_unref(traccount);
988 g_warning("Cannot get transport account for message in outbox!!");
990 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
991 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
994 g_object_unref (folder);
1000 open_msg_cb (ModestMailOperation *mail_op,
1007 ModestWindowMgr *mgr = NULL;
1008 ModestWindow *parent_win = NULL;
1009 ModestWindow *win = NULL;
1010 gchar *account = NULL;
1011 gboolean open_in_editor = FALSE;
1012 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1014 /* Do nothing if there was any problem with the mail
1015 operation. The error will be shown by the error_handler of
1016 the mail operation */
1017 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1020 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1022 /* Mark header as read */
1023 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1025 account = get_info_from_header (header, &open_in_editor);
1029 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1031 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1033 if (open_in_editor) {
1034 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1035 gchar *from_header = NULL, *acc_name;
1037 from_header = tny_header_dup_from (header);
1039 /* we cannot edit without a valid account... */
1040 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1041 if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1042 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1044 g_free (from_header);
1049 acc_name = modest_utils_get_account_name_from_recipient (from_header);
1050 g_free (from_header);
1056 win = modest_msg_edit_window_new (msg, account, TRUE);
1058 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1060 if (helper->rowref && helper->model) {
1061 win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
1062 helper->model, helper->rowref);
1064 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
1069 /* Register and show new window */
1071 mgr = modest_runtime_get_window_mgr ();
1072 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1073 gtk_widget_destroy (GTK_WIDGET (win));
1076 gtk_widget_show_all (GTK_WIDGET(win));
1079 /* Update toolbar dimming state */
1080 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1081 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1087 g_object_unref (parent_win);
1091 is_memory_full_error (GError *error)
1093 gboolean enough_free_space = TRUE;
1094 GnomeVFSURI *cache_dir_uri;
1095 const gchar *cache_dir;
1096 GnomeVFSFileSize free_space;
1098 cache_dir = tny_account_store_get_cache_dir (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1099 cache_dir_uri = gnome_vfs_uri_new (cache_dir);
1100 if (gnome_vfs_get_volume_free_space (cache_dir_uri, &free_space) == GNOME_VFS_OK) {
1101 if (free_space < MIN_FREE_SPACE)
1102 enough_free_space = FALSE;
1104 gnome_vfs_uri_unref (cache_dir_uri);
1106 if ((error->code == TNY_SYSTEM_ERROR_MEMORY ||
1107 /* When asking for a mail and no space left on device
1108 tinymail returns this error */
1109 error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE ||
1110 /* When the folder summary could not be read or
1112 error->code == TNY_IO_ERROR_WRITE ||
1113 error->code == TNY_IO_ERROR_READ) &&
1114 !enough_free_space) {
1122 check_memory_full_error (GtkWidget *parent_window, GError *err)
1127 if (is_memory_full_error (err))
1128 modest_platform_information_banner (parent_window,
1129 NULL, dgettext("ke-recv",
1130 "cerm_device_memory_full"));
1131 else if (err->code == TNY_SYSTEM_ERROR_MEMORY)
1132 /* If the account was created in memory full
1133 conditions then tinymail won't be able to
1134 connect so it'll return this error code */
1135 modest_platform_information_banner (parent_window,
1136 NULL, _("emev_ui_imap_inbox_select_error"));
1144 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1147 const GError *error;
1148 GObject *win = NULL;
1149 ModestMailOperationStatus status;
1151 win = modest_mail_operation_get_source (mail_op);
1152 error = modest_mail_operation_get_error (mail_op);
1153 status = modest_mail_operation_get_status (mail_op);
1155 /* If the mail op has been cancelled then it's not an error:
1156 don't show any message */
1157 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1158 if (is_memory_full_error ((GError *) error)) {
1159 modest_platform_information_banner ((GtkWidget *) win,
1160 NULL, dgettext("ke-recv",
1161 "cerm_device_memory_full"));
1162 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1163 modest_platform_information_banner ((GtkWidget *) win,
1164 NULL, _("emev_ui_imap_inbox_select_error"));
1165 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1166 error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1167 modest_platform_information_banner ((GtkWidget *) win,
1168 NULL, dgettext ("hildon-common-strings", "sfil_ni_unable_to_open_file_not_found"));
1169 } else if (user_data) {
1170 modest_platform_information_banner ((GtkWidget *) win,
1176 g_object_unref (win);
1180 * Returns the account a list of headers belongs to. It returns a
1181 * *new* reference so don't forget to unref it
1184 get_account_from_header_list (TnyList *headers)
1186 TnyAccount *account = NULL;
1188 if (tny_list_get_length (headers) > 0) {
1189 TnyIterator *iter = tny_list_create_iterator (headers);
1190 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1191 TnyFolder *folder = tny_header_get_folder (header);
1194 g_object_unref (header);
1196 while (!tny_iterator_is_done (iter)) {
1197 header = TNY_HEADER (tny_iterator_get_current (iter));
1198 folder = tny_header_get_folder (header);
1201 g_object_unref (header);
1203 tny_iterator_next (iter);
1208 account = tny_folder_get_account (folder);
1209 g_object_unref (folder);
1213 g_object_unref (header);
1215 g_object_unref (iter);
1221 get_account_from_header (TnyHeader *header)
1223 TnyAccount *account = NULL;
1226 folder = tny_header_get_folder (header);
1229 account = tny_folder_get_account (folder);
1230 g_object_unref (folder);
1237 open_msg_helper_destroyer (gpointer user_data)
1239 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1241 if (helper->banner_info) {
1242 g_free (helper->banner_info->message);
1243 if (helper->banner_info->idle_handler > 0) {
1244 g_source_remove (helper->banner_info->idle_handler);
1245 helper->banner_info->idle_handler = 0;
1247 if (helper->banner_info->banner != NULL) {
1248 gtk_widget_destroy (helper->banner_info->banner);
1249 g_object_unref (helper->banner_info->banner);
1250 helper->banner_info->banner = NULL;
1252 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1253 helper->banner_info = NULL;
1255 g_object_unref (helper->model);
1256 g_object_unref (helper->header);
1257 gtk_tree_row_reference_free (helper->rowref);
1258 g_slice_free (OpenMsgHelper, helper);
1262 open_msg_performer(gboolean canceled,
1264 GtkWindow *parent_window,
1265 TnyAccount *account,
1268 ModestMailOperation *mail_op = NULL;
1270 ModestProtocolType proto;
1271 TnyConnectionStatus status;
1272 gboolean show_open_draft = FALSE;
1273 OpenMsgHelper *helper = NULL;
1275 helper = (OpenMsgHelper *) user_data;
1277 status = tny_account_get_connection_status (account);
1278 if (err || canceled) {
1279 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1280 /* Free the helper */
1281 open_msg_helper_destroyer (helper);
1283 /* In memory full conditions we could get this error here */
1284 check_memory_full_error ((GtkWidget *) parent_window, err);
1289 /* Get the error message depending on the protocol */
1290 proto = modest_tny_account_get_protocol_type (account);
1291 if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1292 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1295 ModestProtocol *protocol;
1296 ModestProtocolRegistry *protocol_registry;
1299 protocol_registry = modest_runtime_get_protocol_registry ();
1300 subject = tny_header_dup_subject (helper->header);
1302 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1303 error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1307 if (error_msg == NULL) {
1308 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1311 if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1313 MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1315 TnyFolderType folder_type;
1317 folder = tny_header_get_folder (helper->header);
1318 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1319 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1320 g_object_unref (folder);
1323 #ifdef MODEST_TOOLKIT_HILDON2
1325 gchar *account_name = get_info_from_header (helper->header, &is_draft);
1328 ModestWindow *window;
1329 GtkWidget *header_view;
1332 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1333 uid = modest_tny_folder_get_header_unique_id (helper->header);
1335 window = modest_msg_view_window_new_from_header_view
1336 (MODEST_HEADER_VIEW (header_view), account_name, uid, helper->rowref);
1337 if (window != NULL) {
1338 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1340 gtk_widget_destroy (GTK_WIDGET (window));
1342 gtk_widget_show_all (GTK_WIDGET(window));
1346 g_free (account_name);
1348 open_msg_helper_destroyer (helper);
1351 g_free (account_name);
1353 /* Create the mail operation */
1355 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1356 modest_ui_actions_disk_operations_error_handler,
1358 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1361 if (show_open_draft) {
1362 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1363 #ifdef MODEST_TOOLKIT_HILDON2
1364 helper->banner_info->message = g_strdup (_("mail_me_opening"));
1366 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1368 helper->banner_info->banner = NULL;
1369 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1370 helper->banner_info);
1374 headers = TNY_LIST (tny_simple_list_new ());
1375 tny_list_prepend (headers, G_OBJECT (helper->header));
1376 modest_mail_operation_get_msgs_full (mail_op,
1380 open_msg_helper_destroyer);
1381 g_object_unref (headers);
1386 g_object_unref (mail_op);
1387 g_object_unref (account);
1391 * This function is used by both modest_ui_actions_on_open and
1392 * modest_ui_actions_on_header_activated. This way we always do the
1393 * same when trying to open messages.
1396 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1398 ModestWindowMgr *mgr = NULL;
1399 TnyAccount *account;
1400 gboolean cached = FALSE;
1402 GtkWidget *header_view = NULL;
1403 OpenMsgHelper *helper;
1404 ModestWindow *window;
1406 g_return_if_fail (header != NULL && rowref != NULL);
1408 mgr = modest_runtime_get_window_mgr ();
1411 header_view = get_header_view_from_window (MODEST_WINDOW (win));
1412 if (header_view == NULL)
1415 /* Get the account */
1416 account = get_account_from_header (header);
1421 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1423 /* Do not open again the message and present the
1424 window to the user */
1427 #ifndef MODEST_TOOLKIT_HILDON2
1428 gtk_window_present (GTK_WINDOW (window));
1431 /* the header has been registered already, we don't do
1432 * anything but wait for the window to come up*/
1433 g_debug ("header %p already registered, waiting for window", header);
1438 /* Open each message */
1439 cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1441 /* Allways download if we are online. */
1442 if (!tny_device_is_online (modest_runtime_get_device ())) {
1445 /* If ask for user permission to download the messages */
1446 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1447 _("mcen_nc_get_msg"));
1449 /* End if the user does not want to continue */
1450 if (response == GTK_RESPONSE_CANCEL) {
1456 /* We register the window for opening */
1457 modest_window_mgr_register_header (mgr, header, NULL);
1459 /* Create the helper. We need to get a reference to the model
1460 here because it could change while the message is readed
1461 (the user could switch between folders) */
1462 helper = g_slice_new (OpenMsgHelper);
1463 helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1464 helper->header = g_object_ref (header);
1465 helper->rowref = gtk_tree_row_reference_copy (rowref);
1466 helper->banner_info = NULL;
1468 /* Connect to the account and perform */
1470 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1471 open_msg_performer, helper);
1473 /* Call directly the performer, do not need to connect */
1474 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1475 g_object_ref (account), helper);
1480 g_object_unref (account);
1484 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1491 /* we check for low-mem; in that case, show a warning, and don't allow
1494 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1498 headers = get_selected_headers (win);
1502 headers_count = tny_list_get_length (headers);
1503 if (headers_count != 1) {
1504 if (headers_count > 1) {
1505 /* Don't allow activation if there are more than one message selected */
1506 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1509 g_object_unref (headers);
1513 iter = tny_list_create_iterator (headers);
1514 header = TNY_HEADER (tny_iterator_get_current (iter));
1515 g_object_unref (iter);
1519 open_msg_from_header (header, NULL, win);
1520 g_object_unref (header);
1523 g_object_unref(headers);
1527 rf_helper_window_closed (gpointer data,
1530 ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1532 helper->parent_window = NULL;
1535 static ReplyForwardHelper*
1536 create_reply_forward_helper (ReplyForwardAction action,
1538 guint reply_forward_type,
1541 ReplyForwardHelper *rf_helper = NULL;
1542 const gchar *active_acc = modest_window_get_active_account (win);
1544 rf_helper = g_slice_new0 (ReplyForwardHelper);
1545 rf_helper->reply_forward_type = reply_forward_type;
1546 rf_helper->action = action;
1547 rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1548 rf_helper->header = (header) ? g_object_ref (header) : NULL;
1549 rf_helper->account_name = (active_acc) ?
1550 g_strdup (active_acc) :
1551 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1553 /* Note that window could be destroyed just AFTER calling
1554 register_window so we must ensure that this pointer does
1555 not hold invalid references */
1556 if (rf_helper->parent_window)
1557 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1558 rf_helper_window_closed, rf_helper);
1564 free_reply_forward_helper (gpointer data)
1566 ReplyForwardHelper *helper;
1568 helper = (ReplyForwardHelper *) data;
1569 g_free (helper->account_name);
1571 g_object_unref (helper->header);
1572 if (helper->parent_window)
1573 g_object_weak_unref (G_OBJECT (helper->parent_window),
1574 rf_helper_window_closed, helper);
1575 g_slice_free (ReplyForwardHelper, helper);
1579 reply_forward_cb (ModestMailOperation *mail_op,
1586 TnyMsg *new_msg = NULL;
1587 ReplyForwardHelper *rf_helper;
1588 ModestWindow *msg_win = NULL;
1589 ModestEditType edit_type;
1591 TnyAccount *account = NULL;
1592 ModestWindowMgr *mgr = NULL;
1593 gchar *signature = NULL;
1594 gboolean use_signature;
1596 /* If there was any error. The mail operation could be NULL,
1597 this means that we already have the message downloaded and
1598 that we didn't do a mail operation to retrieve it */
1599 rf_helper = (ReplyForwardHelper *) user_data;
1600 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1603 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1604 rf_helper->account_name);
1605 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(),
1606 rf_helper->account_name,
1609 /* Create reply mail */
1610 switch (rf_helper->action) {
1613 modest_tny_msg_create_reply_msg (msg, header, from,
1614 (use_signature) ? signature : NULL,
1615 rf_helper->reply_forward_type,
1616 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1618 case ACTION_REPLY_TO_ALL:
1620 modest_tny_msg_create_reply_msg (msg, header, from,
1621 (use_signature) ? signature : NULL,
1622 rf_helper->reply_forward_type,
1623 MODEST_TNY_MSG_REPLY_MODE_ALL);
1624 edit_type = MODEST_EDIT_TYPE_REPLY;
1626 case ACTION_FORWARD:
1628 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1629 rf_helper->reply_forward_type);
1630 edit_type = MODEST_EDIT_TYPE_FORWARD;
1633 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1635 g_return_if_reached ();
1643 g_warning ("%s: failed to create message\n", __FUNCTION__);
1647 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1648 rf_helper->account_name,
1649 TNY_ACCOUNT_TYPE_STORE);
1651 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1655 /* Create and register the windows */
1656 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1657 mgr = modest_runtime_get_window_mgr ();
1658 modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1660 /* Note that register_window could have deleted the account */
1661 if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1662 gdouble parent_zoom;
1664 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1665 modest_window_set_zoom (msg_win, parent_zoom);
1668 /* Show edit window */
1669 gtk_widget_show_all (GTK_WIDGET (msg_win));
1672 /* We always unregister the header because the message is
1673 forwarded or replied so the original one is no longer
1675 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1678 g_object_unref (G_OBJECT (new_msg));
1680 g_object_unref (G_OBJECT (account));
1681 free_reply_forward_helper (rf_helper);
1684 /* Checks a list of headers. If any of them are not currently
1685 * downloaded (CACHED) then returns TRUE else returns FALSE.
1688 header_list_count_uncached_msgs (TnyList *header_list)
1691 gint uncached_messages = 0;
1693 iter = tny_list_create_iterator (header_list);
1694 while (!tny_iterator_is_done (iter)) {
1697 header = TNY_HEADER (tny_iterator_get_current (iter));
1699 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1700 uncached_messages ++;
1701 g_object_unref (header);
1704 tny_iterator_next (iter);
1706 g_object_unref (iter);
1708 return uncached_messages;
1711 /* Returns FALSE if the user does not want to download the
1712 * messages. Returns TRUE if the user allowed the download.
1715 connect_to_get_msg (ModestWindow *win,
1716 gint num_of_uncached_msgs,
1717 TnyAccount *account)
1719 GtkResponseType response;
1721 /* Allways download if we are online. */
1722 if (tny_device_is_online (modest_runtime_get_device ()))
1725 /* If offline, then ask for user permission to download the messages */
1726 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1727 ngettext("mcen_nc_get_msg",
1729 num_of_uncached_msgs));
1731 if (response == GTK_RESPONSE_CANCEL)
1734 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1738 reply_forward_performer (gboolean canceled,
1740 GtkWindow *parent_window,
1741 TnyAccount *account,
1744 ReplyForwardHelper *rf_helper = NULL;
1745 ModestMailOperation *mail_op;
1747 rf_helper = (ReplyForwardHelper *) user_data;
1749 if (canceled || err) {
1750 free_reply_forward_helper (rf_helper);
1754 /* Retrieve the message */
1755 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1756 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1757 modest_ui_actions_disk_operations_error_handler,
1759 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1760 modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1763 g_object_unref(mail_op);
1767 * Common code for the reply and forward actions
1770 reply_forward (ReplyForwardAction action, ModestWindow *win)
1772 ReplyForwardHelper *rf_helper = NULL;
1773 guint reply_forward_type;
1775 g_return_if_fail (MODEST_IS_WINDOW(win));
1777 /* we check for low-mem; in that case, show a warning, and don't allow
1778 * reply/forward (because it could potentially require a lot of memory */
1779 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1783 /* we need an account when editing */
1784 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1785 if (!modest_ui_actions_run_account_setup_wizard (win))
1789 reply_forward_type =
1790 modest_conf_get_int (modest_runtime_get_conf (),
1791 (action == ACTION_FORWARD) ?
1792 MODEST_CONF_FORWARD_TYPE :
1793 MODEST_CONF_REPLY_TYPE,
1796 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1798 TnyHeader *header = NULL;
1799 /* Get header and message. Do not free them here, the
1800 reply_forward_cb must do it */
1801 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1802 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1804 if (msg && header) {
1806 rf_helper = create_reply_forward_helper (action, win,
1807 reply_forward_type, header);
1808 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1810 g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1814 g_object_unref (msg);
1816 g_object_unref (header);
1818 TnyHeader *header = NULL;
1820 gboolean do_retrieve = TRUE;
1821 TnyList *header_list = NULL;
1823 header_list = get_selected_headers (win);
1826 /* Check that only one message is selected for replying */
1827 if (tny_list_get_length (header_list) != 1) {
1828 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1829 NULL, _("mcen_ib_select_one_message"));
1830 g_object_unref (header_list);
1834 /* Only reply/forward to one message */
1835 iter = tny_list_create_iterator (header_list);
1836 header = TNY_HEADER (tny_iterator_get_current (iter));
1837 g_object_unref (iter);
1839 /* Retrieve messages */
1840 do_retrieve = (action == ACTION_FORWARD) ||
1841 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1844 TnyAccount *account = NULL;
1845 TnyFolder *folder = NULL;
1846 gdouble download = TRUE;
1847 guint uncached_msgs = 0;
1849 folder = tny_header_get_folder (header);
1851 goto do_retrieve_frees;
1852 account = tny_folder_get_account (folder);
1854 goto do_retrieve_frees;
1856 uncached_msgs = header_list_count_uncached_msgs (header_list);
1858 if (uncached_msgs > 0) {
1859 /* Allways download if we are online. */
1860 if (!tny_device_is_online (modest_runtime_get_device ())) {
1863 /* If ask for user permission to download the messages */
1864 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1865 ngettext("mcen_nc_get_msg",
1869 /* End if the user does not want to continue */
1870 if (response == GTK_RESPONSE_CANCEL)
1877 rf_helper = create_reply_forward_helper (action, win,
1878 reply_forward_type, header);
1879 if (uncached_msgs > 0) {
1880 modest_platform_connect_and_perform (GTK_WINDOW (win),
1882 reply_forward_performer,
1885 reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
1886 account, rf_helper);
1891 g_object_unref (account);
1893 g_object_unref (folder);
1895 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1898 g_object_unref (header_list);
1899 g_object_unref (header);
1904 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1906 g_return_if_fail (MODEST_IS_WINDOW(win));
1908 reply_forward (ACTION_REPLY, win);
1912 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1914 g_return_if_fail (MODEST_IS_WINDOW(win));
1916 reply_forward (ACTION_FORWARD, win);
1920 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1922 g_return_if_fail (MODEST_IS_WINDOW(win));
1924 reply_forward (ACTION_REPLY_TO_ALL, win);
1928 modest_ui_actions_on_next (GtkAction *action,
1929 ModestWindow *window)
1931 if (MODEST_IS_MAIN_WINDOW (window)) {
1932 GtkWidget *header_view;
1934 header_view = modest_main_window_get_child_widget (
1935 MODEST_MAIN_WINDOW(window),
1936 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1940 modest_header_view_select_next (
1941 MODEST_HEADER_VIEW(header_view));
1942 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1943 modest_msg_view_window_select_next_message (
1944 MODEST_MSG_VIEW_WINDOW (window));
1946 g_return_if_reached ();
1951 modest_ui_actions_on_prev (GtkAction *action,
1952 ModestWindow *window)
1954 g_return_if_fail (MODEST_IS_WINDOW(window));
1956 if (MODEST_IS_MAIN_WINDOW (window)) {
1957 GtkWidget *header_view;
1958 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1959 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1963 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1964 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1965 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1967 g_return_if_reached ();
1972 modest_ui_actions_on_sort (GtkAction *action,
1973 ModestWindow *window)
1975 GtkWidget *header_view = NULL;
1977 g_return_if_fail (MODEST_IS_WINDOW(window));
1979 if (MODEST_IS_MAIN_WINDOW (window)) {
1980 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1981 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1982 #ifdef MODEST_TOOLKIT_HILDON2
1983 } else if (MODEST_IS_HEADER_WINDOW (window)) {
1984 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1989 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1994 /* Show sorting dialog */
1995 modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1999 new_messages_arrived (ModestMailOperation *self,
2000 TnyList *new_headers,
2004 gboolean show_visual_notifications;
2006 source = modest_mail_operation_get_source (self);
2007 show_visual_notifications = (source) ? FALSE : TRUE;
2009 g_object_unref (source);
2011 /* Notify new messages have been downloaded. If the
2012 send&receive was invoked by the user then do not show any
2013 visual notification, only play a sound and activate the LED
2014 (for the Maemo version) */
2015 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
2016 modest_platform_on_new_headers_received (new_headers,
2017 show_visual_notifications);
2022 retrieve_all_messages_cb (GObject *source,
2024 guint retrieve_limit)
2030 window = GTK_WINDOW (source);
2031 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2032 num_msgs, retrieve_limit);
2034 /* Ask the user if they want to retrieve all the messages */
2036 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2037 _("mcen_bd_get_all"),
2038 _("mcen_bd_newest_only"));
2039 /* Free and return */
2041 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2045 TnyAccount *account;
2047 gchar *account_name;
2048 gboolean poke_status;
2049 gboolean interactive;
2050 ModestMailOperation *mail_op;
2054 do_send_receive_performer (gboolean canceled,
2056 GtkWindow *parent_window,
2057 TnyAccount *account,
2060 SendReceiveInfo *info;
2062 info = (SendReceiveInfo *) user_data;
2064 if (err || canceled) {
2065 /* In memory full conditions we could get this error here */
2066 check_memory_full_error ((GtkWidget *) parent_window, err);
2068 if (info->mail_op) {
2069 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2075 /* Set send/receive operation in progress */
2076 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2077 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2080 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2081 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2082 G_CALLBACK (on_send_receive_finished),
2085 /* Send & receive. */
2086 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2087 (info->win) ? retrieve_all_messages_cb : NULL,
2088 new_messages_arrived, info->win);
2093 g_object_unref (G_OBJECT (info->mail_op));
2094 if (info->account_name)
2095 g_free (info->account_name);
2097 g_object_unref (info->win);
2099 g_object_unref (info->account);
2100 g_slice_free (SendReceiveInfo, info);
2104 * This function performs the send & receive required actions. The
2105 * window is used to create the mail operation. Typically it should
2106 * always be the main window, but we pass it as argument in order to
2110 modest_ui_actions_do_send_receive (const gchar *account_name,
2111 gboolean force_connection,
2112 gboolean poke_status,
2113 gboolean interactive,
2116 gchar *acc_name = NULL;
2117 SendReceiveInfo *info;
2118 ModestTnyAccountStore *acc_store;
2120 /* If no account name was provided then get the current account, and if
2121 there is no current account then pick the default one: */
2122 if (!account_name) {
2124 acc_name = g_strdup (modest_window_get_active_account (win));
2126 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2128 g_printerr ("modest: cannot get default account\n");
2132 acc_name = g_strdup (account_name);
2135 acc_store = modest_runtime_get_account_store ();
2137 /* Create the info for the connect and perform */
2138 info = g_slice_new (SendReceiveInfo);
2139 info->account_name = acc_name;
2140 info->win = (win) ? g_object_ref (win) : NULL;
2141 info->poke_status = poke_status;
2142 info->interactive = interactive;
2143 info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
2144 TNY_ACCOUNT_TYPE_STORE);
2145 /* We need to create the operation here, because otherwise it
2146 could happen that the queue emits the queue-empty signal
2147 while we're trying to connect the account */
2148 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2149 modest_ui_actions_disk_operations_error_handler,
2151 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2153 /* Invoke the connect and perform */
2154 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2155 force_connection, info->account,
2156 do_send_receive_performer, info);
2161 modest_ui_actions_do_cancel_send (const gchar *account_name,
2164 TnyTransportAccount *transport_account;
2165 TnySendQueue *send_queue = NULL;
2166 GError *error = NULL;
2168 /* Get transport account */
2170 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2171 (modest_runtime_get_account_store(),
2173 TNY_ACCOUNT_TYPE_TRANSPORT));
2174 if (!transport_account) {
2175 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2180 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2181 if (!TNY_IS_SEND_QUEUE(send_queue)) {
2182 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2183 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2184 "modest: could not find send queue for account\n");
2186 /* Cancel the current send */
2187 tny_account_cancel (TNY_ACCOUNT (transport_account));
2189 /* Suspend all pending messages */
2190 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2194 if (transport_account != NULL)
2195 g_object_unref (G_OBJECT (transport_account));
2199 modest_ui_actions_cancel_send_all (ModestWindow *win)
2201 GSList *account_names, *iter;
2203 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2206 iter = account_names;
2208 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2209 iter = g_slist_next (iter);
2212 modest_account_mgr_free_account_names (account_names);
2213 account_names = NULL;
2217 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2220 /* Check if accounts exist */
2221 gboolean accounts_exist =
2222 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2224 /* If not, allow the user to create an account before trying to send/receive. */
2225 if (!accounts_exist)
2226 modest_ui_actions_on_accounts (NULL, win);
2228 /* Cancel all sending operaitons */
2229 modest_ui_actions_cancel_send_all (win);
2233 * Refreshes all accounts. This function will be used by automatic
2237 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2238 gboolean force_connection,
2239 gboolean poke_status,
2240 gboolean interactive)
2242 GSList *account_names, *iter;
2244 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2247 iter = account_names;
2249 modest_ui_actions_do_send_receive ((const char*) iter->data,
2251 poke_status, interactive, win);
2252 iter = g_slist_next (iter);
2255 modest_account_mgr_free_account_names (account_names);
2256 account_names = NULL;
2260 * Handler of the click on Send&Receive button in the main toolbar
2263 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2265 /* Check if accounts exist */
2266 gboolean accounts_exist;
2269 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2271 /* If not, allow the user to create an account before trying to send/receive. */
2272 if (!accounts_exist)
2273 modest_ui_actions_on_accounts (NULL, win);
2275 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2276 if (MODEST_IS_MAIN_WINDOW (win)) {
2277 GtkWidget *folder_view;
2278 TnyFolderStore *folder_store;
2281 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2282 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2286 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2289 g_object_unref (folder_store);
2290 /* Refresh the active account. Force the connection if needed
2291 and poke the status of all folders */
2292 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2293 #ifdef MODEST_TOOLKIT_HILDON2
2294 } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2295 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2298 const gchar *active_account;
2299 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2301 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2308 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2311 GtkWidget *header_view;
2313 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2315 header_view = modest_main_window_get_child_widget (main_window,
2316 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2320 conf = modest_runtime_get_conf ();
2322 /* what is saved/restored is depending on the style; thus; we save with
2323 * old style, then update the style, and restore for this new style
2325 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2327 if (modest_header_view_get_style
2328 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2329 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2330 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2332 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2333 MODEST_HEADER_VIEW_STYLE_DETAILS);
2335 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2336 MODEST_CONF_HEADER_VIEW_KEY);
2341 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2343 ModestMainWindow *main_window)
2345 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2346 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2348 /* in the case the folder is empty, show the empty folder message and focus
2350 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2351 if (modest_header_view_is_empty (header_view)) {
2352 TnyFolder *folder = modest_header_view_get_folder (header_view);
2353 GtkWidget *folder_view =
2354 modest_main_window_get_child_widget (main_window,
2355 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2356 if (folder != NULL) {
2357 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2358 g_object_unref (folder);
2360 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2364 /* If no header has been selected then exit */
2369 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2370 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2372 /* Update toolbar dimming state */
2373 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2374 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2378 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2381 ModestWindow *window)
2383 GtkWidget *open_widget;
2384 GtkTreeRowReference *rowref;
2386 g_return_if_fail (MODEST_IS_WINDOW(window));
2387 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2388 g_return_if_fail (TNY_IS_HEADER (header));
2390 if (modest_header_view_count_selected_headers (header_view) > 1) {
2391 /* Don't allow activation if there are more than one message selected */
2392 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2396 /* we check for low-mem; in that case, show a warning, and don't allow
2397 * activating headers
2399 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2402 if (MODEST_IS_MAIN_WINDOW (window)) {
2403 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2404 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2405 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2409 rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2410 open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2411 gtk_tree_row_reference_free (rowref);
2415 set_active_account_from_tny_account (TnyAccount *account,
2416 ModestWindow *window)
2418 const gchar *server_acc_name = tny_account_get_id (account);
2420 /* We need the TnyAccount provided by the
2421 account store because that is the one that
2422 knows the name of the Modest account */
2423 TnyAccount *modest_server_account = modest_server_account =
2424 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2425 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2427 if (!modest_server_account) {
2428 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2432 /* Update active account, but only if it's not a pseudo-account */
2433 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2434 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2435 const gchar *modest_acc_name =
2436 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2437 if (modest_acc_name)
2438 modest_window_set_active_account (window, modest_acc_name);
2441 g_object_unref (modest_server_account);
2446 folder_refreshed_cb (ModestMailOperation *mail_op,
2450 ModestMainWindow *win = NULL;
2451 GtkWidget *folder_view;
2452 const GError *error;
2454 g_return_if_fail (TNY_IS_FOLDER (folder));
2456 win = MODEST_MAIN_WINDOW (user_data);
2458 /* Check if the operation failed due to memory low conditions */
2459 error = modest_mail_operation_get_error (mail_op);
2460 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2461 error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2462 modest_platform_run_information_dialog (GTK_WINDOW (win),
2463 dgettext("ke-recv","memr_ib_operation_disabled"),
2469 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2472 TnyFolderStore *current_folder;
2474 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2475 if (current_folder) {
2476 gboolean different = ((TnyFolderStore *) folder != current_folder);
2477 g_object_unref (current_folder);
2483 /* Check if folder is empty and set headers view contents style */
2484 if (tny_folder_get_all_count (folder) == 0)
2485 modest_main_window_set_contents_style (win,
2486 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2491 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2492 TnyFolderStore *folder_store,
2494 ModestMainWindow *main_window)
2497 GtkWidget *header_view;
2499 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2501 header_view = modest_main_window_get_child_widget(main_window,
2502 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2506 conf = modest_runtime_get_conf ();
2508 if (TNY_IS_ACCOUNT (folder_store)) {
2510 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2512 /* Show account details */
2513 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2516 if (TNY_IS_FOLDER (folder_store) && selected) {
2517 TnyAccount *account;
2518 const gchar *account_name = NULL;
2520 /* Update the active account */
2521 account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2523 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2525 modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2526 g_object_unref (account);
2530 /* Set the header style by default, it could
2531 be changed later by the refresh callback to
2533 modest_main_window_set_contents_style (main_window,
2534 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2536 /* Set folder on header view. This function
2537 will call tny_folder_refresh_async so we
2538 pass a callback that will be called when
2539 finished. We use that callback to set the
2540 empty view if there are no messages */
2541 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2542 TNY_FOLDER (folder_store),
2544 MODEST_WINDOW (main_window),
2545 folder_refreshed_cb,
2548 /* Restore configuration. We need to do this
2549 *after* the set_folder because the widget
2550 memory asks the header view about its
2552 modest_widget_memory_restore (modest_runtime_get_conf (),
2553 G_OBJECT(header_view),
2554 MODEST_CONF_HEADER_VIEW_KEY);
2556 /* No need to save the header view
2557 configuration for Maemo because it only
2558 saves the sorting stuff and that it's
2559 already being done by the sort
2560 dialog. Remove it when the GNOME version
2561 has the same behaviour */
2562 #ifdef MODEST_TOOLKIT_GTK
2563 if (modest_main_window_get_contents_style (main_window) ==
2564 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2565 modest_widget_memory_save (conf, G_OBJECT (header_view),
2566 MODEST_CONF_HEADER_VIEW_KEY);
2568 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2572 /* Update dimming state */
2573 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2574 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2578 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2585 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2587 online = tny_device_is_online (modest_runtime_get_device());
2590 /* already online -- the item is simply not there... */
2591 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2593 GTK_MESSAGE_WARNING,
2595 _("The %s you selected cannot be found"),
2597 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2598 gtk_dialog_run (GTK_DIALOG(dialog));
2600 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2603 _("mcen_bd_dialog_cancel"),
2604 GTK_RESPONSE_REJECT,
2605 _("mcen_bd_dialog_ok"),
2606 GTK_RESPONSE_ACCEPT,
2608 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2609 "Do you want to get online?"), item);
2610 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2611 gtk_label_new (txt), FALSE, FALSE, 0);
2612 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2615 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2616 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2617 /* TODO: Comment about why is this commented out: */
2618 /* modest_platform_connect_and_wait (); */
2621 gtk_widget_destroy (dialog);
2625 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2628 /* g_message ("%s %s", __FUNCTION__, link); */
2633 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2636 modest_platform_activate_uri (link);
2640 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2643 modest_platform_show_uri_popup (link);
2647 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2650 /* we check for low-mem; in that case, show a warning, and don't allow
2651 * viewing attachments
2653 if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2656 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2660 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2661 const gchar *address,
2664 /* g_message ("%s %s", __FUNCTION__, address); */
2668 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2669 TnyMsg *saved_draft,
2672 ModestMsgEditWindow *edit_window;
2674 /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2675 #ifndef MODEST_TOOLKIT_HILDON2
2676 ModestMainWindow *win;
2678 /* FIXME. Make the header view sensitive again. This is a
2679 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2681 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2682 modest_runtime_get_window_mgr(), FALSE));
2684 GtkWidget *hdrview = modest_main_window_get_child_widget(
2685 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2686 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2690 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2692 /* Set draft is there was no error */
2693 if (!modest_mail_operation_get_error (mail_op))
2694 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2696 g_object_unref(edit_window);
2700 enough_space_for_message (ModestMsgEditWindow *edit_window,
2703 TnyAccountStore *acc_store;
2704 guint64 available_disk, expected_size;
2709 acc_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store());
2710 available_disk = modest_utils_get_available_space (NULL);
2711 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2712 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2717 /* Double check: memory full condition or message too big */
2718 if (available_disk < MIN_FREE_SPACE ||
2719 expected_size > available_disk) {
2721 modest_platform_information_banner (NULL, NULL,
2723 "cerm_device_memory_full"));
2728 * djcb: if we're in low-memory state, we only allow for
2729 * saving messages smaller than
2730 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2731 * should still allow for sending anything critical...
2733 if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2734 modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2738 * djcb: we also make sure that the attachments are smaller than the max size
2739 * this is for the case where we'd try to forward a message with attachments
2740 * bigger than our max allowed size, or sending an message from drafts which
2741 * somehow got past our checks when attaching.
2743 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2744 modest_platform_run_information_dialog (
2745 GTK_WINDOW(edit_window),
2746 dgettext("ke-recv","memr_ib_operation_disabled"),
2755 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2757 TnyTransportAccount *transport_account;
2758 ModestMailOperation *mail_operation;
2760 gchar *account_name, *from;
2761 ModestAccountMgr *account_mgr;
2762 gboolean had_error = FALSE;
2763 ModestMainWindow *win = NULL;
2765 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2767 data = modest_msg_edit_window_get_msg_data (edit_window);
2770 if (!enough_space_for_message (edit_window, data)) {
2771 modest_msg_edit_window_free_msg_data (edit_window, data);
2775 account_name = g_strdup (data->account_name);
2776 account_mgr = modest_runtime_get_account_mgr();
2778 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2780 account_name = modest_account_mgr_get_default_account (account_mgr);
2781 if (!account_name) {
2782 g_printerr ("modest: no account found\n");
2783 modest_msg_edit_window_free_msg_data (edit_window, data);
2787 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2788 account_name = g_strdup (data->account_name);
2792 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2793 (modest_runtime_get_account_store (),
2795 TNY_ACCOUNT_TYPE_TRANSPORT));
2796 if (!transport_account) {
2797 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2798 g_free (account_name);
2799 modest_msg_edit_window_free_msg_data (edit_window, data);
2802 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2804 /* Create the mail operation */
2805 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2807 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2809 modest_mail_operation_save_to_drafts (mail_operation,
2821 data->priority_flags,
2822 on_save_to_drafts_cb,
2823 g_object_ref(edit_window));
2825 #ifdef MODEST_TOOLKIT_HILDON2
2826 /* In hildon2 we always show the information banner on saving to drafts.
2827 * It will be a system information banner in this case.
2829 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2830 modest_platform_information_banner (NULL, NULL, text);
2833 /* Use the main window as the parent of the banner, if the
2834 main window does not exist it won't be shown, if the parent
2835 window exists then it's properly shown. We don't use the
2836 editor window because it could be closed (save to drafts
2837 could happen after closing the window */
2838 win = (ModestMainWindow *)
2839 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2841 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2842 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2846 modest_msg_edit_window_set_modified (edit_window, FALSE);
2850 g_free (account_name);
2851 g_object_unref (G_OBJECT (transport_account));
2852 g_object_unref (G_OBJECT (mail_operation));
2854 modest_msg_edit_window_free_msg_data (edit_window, data);
2857 * If the drafts folder is selected then make the header view
2858 * insensitive while the message is being saved to drafts
2859 * (it'll be sensitive again in on_save_to_drafts_cb()). This
2860 * is not very clean but it avoids letting the drafts folder
2861 * in an inconsistent state: the user could edit the message
2862 * being saved and undesirable things would happen.
2863 * In the average case the user won't notice anything at
2864 * all. In the worst case (the user is editing a really big
2865 * file from Drafts) the header view will be insensitive
2866 * during the saving process (10 or 20 seconds, depending on
2867 * the message). Anyway this is just a quick workaround: once
2868 * we find a better solution it should be removed
2869 * See NB#65125 (commend #18) for details.
2871 if (!had_error && win != NULL) {
2872 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2873 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2875 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2877 if (modest_tny_folder_is_local_folder(folder)) {
2878 TnyFolderType folder_type;
2879 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2880 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2881 GtkWidget *hdrview = modest_main_window_get_child_widget(
2882 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2883 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2887 if (folder != NULL) g_object_unref(folder);
2894 /* For instance, when clicking the Send toolbar button when editing a message: */
2896 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2898 TnyTransportAccount *transport_account = NULL;
2899 gboolean had_error = FALSE;
2901 ModestAccountMgr *account_mgr;
2902 gchar *account_name;
2904 ModestMailOperation *mail_operation;
2906 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2908 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2911 data = modest_msg_edit_window_get_msg_data (edit_window);
2914 if (!enough_space_for_message (edit_window, data)) {
2915 modest_msg_edit_window_free_msg_data (edit_window, data);
2919 account_mgr = modest_runtime_get_account_mgr();
2920 account_name = g_strdup (data->account_name);
2922 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2925 account_name = modest_account_mgr_get_default_account (account_mgr);
2927 if (!account_name) {
2928 modest_msg_edit_window_free_msg_data (edit_window, data);
2929 /* Run account setup wizard */
2930 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2935 /* Get the currently-active transport account for this modest account: */
2936 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2938 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2939 (modest_runtime_get_account_store (),
2940 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2943 if (!transport_account) {
2944 modest_msg_edit_window_free_msg_data (edit_window, data);
2945 /* Run account setup wizard */
2946 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2951 /* Create the mail operation */
2952 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2953 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
2954 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2956 modest_mail_operation_send_new_mail (mail_operation,
2968 data->priority_flags);
2970 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2971 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2974 if (modest_mail_operation_get_error (mail_operation) != NULL) {
2975 const GError *error = modest_mail_operation_get_error (mail_operation);
2976 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
2977 error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2978 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2979 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2986 g_free (account_name);
2987 g_object_unref (G_OBJECT (transport_account));
2988 g_object_unref (G_OBJECT (mail_operation));
2990 modest_msg_edit_window_free_msg_data (edit_window, data);
2993 modest_msg_edit_window_set_sent (edit_window, TRUE);
2995 /* Save settings and close the window: */
2996 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3003 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3004 ModestMsgEditWindow *window)
3006 ModestMsgEditFormatState *format_state = NULL;
3008 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3009 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3011 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3014 format_state = modest_msg_edit_window_get_format_state (window);
3015 g_return_if_fail (format_state != NULL);
3017 format_state->bold = gtk_toggle_action_get_active (action);
3018 modest_msg_edit_window_set_format_state (window, format_state);
3019 g_free (format_state);
3024 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3025 ModestMsgEditWindow *window)
3027 ModestMsgEditFormatState *format_state = NULL;
3029 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3030 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3032 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3035 format_state = modest_msg_edit_window_get_format_state (window);
3036 g_return_if_fail (format_state != NULL);
3038 format_state->italics = gtk_toggle_action_get_active (action);
3039 modest_msg_edit_window_set_format_state (window, format_state);
3040 g_free (format_state);
3045 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3046 ModestMsgEditWindow *window)
3048 ModestMsgEditFormatState *format_state = NULL;
3050 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3051 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3053 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3056 format_state = modest_msg_edit_window_get_format_state (window);
3057 g_return_if_fail (format_state != NULL);
3059 format_state->bullet = gtk_toggle_action_get_active (action);
3060 modest_msg_edit_window_set_format_state (window, format_state);
3061 g_free (format_state);
3066 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3067 GtkRadioAction *selected,
3068 ModestMsgEditWindow *window)
3070 ModestMsgEditFormatState *format_state = NULL;
3071 GtkJustification value;
3073 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3075 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3078 value = gtk_radio_action_get_current_value (selected);
3080 format_state = modest_msg_edit_window_get_format_state (window);
3081 g_return_if_fail (format_state != NULL);
3083 format_state->justification = value;
3084 modest_msg_edit_window_set_format_state (window, format_state);
3085 g_free (format_state);
3089 modest_ui_actions_on_select_editor_color (GtkAction *action,
3090 ModestMsgEditWindow *window)
3092 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3093 g_return_if_fail (GTK_IS_ACTION (action));
3095 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3098 modest_msg_edit_window_select_color (window);
3102 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3103 ModestMsgEditWindow *window)
3105 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3106 g_return_if_fail (GTK_IS_ACTION (action));
3108 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3111 modest_msg_edit_window_select_background_color (window);
3115 modest_ui_actions_on_insert_image (GtkAction *action,
3116 ModestMsgEditWindow *window)
3118 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3119 g_return_if_fail (GTK_IS_ACTION (action));
3122 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3125 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3128 modest_msg_edit_window_insert_image (window);
3132 modest_ui_actions_on_attach_file (GtkAction *action,
3133 ModestMsgEditWindow *window)
3135 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3136 g_return_if_fail (GTK_IS_ACTION (action));
3138 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3141 modest_msg_edit_window_offer_attach_file (window);
3145 modest_ui_actions_on_remove_attachments (GtkAction *action,
3146 ModestMsgEditWindow *window)
3148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3149 g_return_if_fail (GTK_IS_ACTION (action));
3151 modest_msg_edit_window_remove_attachments (window, NULL);
3155 #ifndef MODEST_TOOLKIT_GTK
3160 TnyFolderStore *folder;
3161 } CreateFolderHelper;
3164 show_create_folder_in_timeout (gpointer data)
3166 CreateFolderHelper *helper = (CreateFolderHelper *) data;
3168 /* Remove the timeout ASAP, we can not wait until the dialog
3169 is shown because it could take a lot of time and so the
3170 timeout could be called twice or more times */
3171 g_source_remove (helper->handler);
3173 gdk_threads_enter ();
3174 do_create_folder (helper->win, helper->folder, helper->name);
3175 gdk_threads_leave ();
3177 g_object_unref (helper->win);
3178 g_object_unref (helper->folder);
3179 g_free (helper->name);
3180 g_slice_free (CreateFolderHelper, helper);
3187 do_create_folder_cb (ModestMailOperation *mail_op,
3188 TnyFolderStore *parent_folder,
3189 TnyFolder *new_folder,
3192 gchar *suggested_name = (gchar *) user_data;
3193 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3195 if (modest_mail_operation_get_error (mail_op)) {
3197 /* Show an error. If there was some problem writing to
3198 disk, show it, otherwise show the generic folder
3199 create error. We do it here and not in an error
3200 handler because the call to do_create_folder will
3201 stop the main loop in a gtk_dialog_run and then,
3202 the message won't be shown until that dialog is
3204 modest_ui_actions_disk_operations_error_handler (mail_op,
3205 _("mail_in_ui_folder_create_error"));
3207 /* Try again. Do *NOT* show any error because the mail
3208 operations system will do it for us because we
3209 created the mail_op with new_with_error_handler */
3210 #ifndef MODEST_TOOLKIT_GTK
3211 CreateFolderHelper *helper;
3212 helper = g_slice_new0 (CreateFolderHelper);
3213 helper->name = g_strdup (suggested_name);
3214 helper->folder = g_object_ref (parent_folder);
3215 helper->win = g_object_ref (source_win);
3217 /* Ugly but neccesary stuff. The problem is that the
3218 dialog when is shown calls a function that destroys
3219 all the temporary windows, so the banner is
3221 helper->handler = g_timeout_add (2000, show_create_folder_in_timeout, helper);
3223 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3226 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3227 * FIXME: any other? */
3228 GtkWidget *folder_view;
3230 if (MODEST_IS_MAIN_WINDOW(source_win))
3232 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3233 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3235 folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3236 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3238 /* Select the newly created folder. It could happen
3239 that the widget is no longer there (i.e. the window
3240 has been destroyed, so we need to check this */