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-protocol-info.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-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard-dialog.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
83 #include <gtkhtml/gtkhtml.h>
85 typedef struct _GetMsgAsyncHelper {
87 ModestMailOperation *mail_op;
94 typedef enum _ReplyForwardAction {
100 typedef struct _ReplyForwardHelper {
101 guint reply_forward_type;
102 ReplyForwardAction action;
104 GtkWidget *parent_window;
105 } ReplyForwardHelper;
107 typedef struct _MoveToHelper {
108 GtkTreeRowReference *reference;
112 typedef struct _PasteAsAttachmentHelper {
113 ModestMsgEditWindow *window;
115 } PasteAsAttachmentHelper;
119 * The do_headers_action uses this kind of functions to perform some
120 * action to each member of a list of headers
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
124 static void do_headers_action (ModestWindow *win,
128 static void open_msg_cb (ModestMailOperation *mail_op,
135 static void reply_forward_cb (ModestMailOperation *mail_op,
142 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
144 static void folder_refreshed_cb (ModestMailOperation *mail_op,
148 static void on_send_receive_finished (ModestMailOperation *mail_op,
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
153 static gboolean connect_to_get_msg (ModestWindow *win,
154 gint num_of_uncached_msgs,
155 TnyAccount *account);
157 static gboolean remote_folder_is_pop (TnyFolderStore *folder);
159 static void do_create_folder (GtkWindow *window,
160 TnyFolderStore *parent_folder,
161 const gchar *suggested_name);
163 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
165 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
167 static void transfer_messages_helper (GtkWindow *win,
168 TnyFolder *src_folder,
170 TnyFolder *dst_folder);
173 * This function checks whether a TnyFolderStore is a pop account
176 remote_folder_is_pop (TnyFolderStore *folder)
178 const gchar *proto = NULL;
179 TnyAccount *account = NULL;
181 g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
183 account = get_account_from_folder_store (folder);
184 proto = tny_account_get_proto (account);
185 g_object_unref (account);
187 return (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
190 /* FIXME: this should be merged with the similar code in modest-account-view-window */
191 /* Show the account creation wizard dialog.
192 * returns: TRUE if an account was created. FALSE if the user cancelled.
195 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
197 gboolean result = FALSE;
198 GtkWindow *dialog, *wizard;
199 gint dialog_response;
201 /* Show the easy-setup wizard: */
202 dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
204 /* old wizard is active already;
206 gtk_window_present (GTK_WINDOW(dialog));
211 /* there is no such wizard yet */
212 wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
213 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
215 /* always present a main window in the background
216 * we do it here, so we cannot end up with two wizards (as this
217 * function might be called in modest_window_mgr_get_main_window as well */
219 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
220 TRUE); /* create if not existent */
222 /* make sure the mainwindow is visible */
223 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
224 gtk_widget_show_all (GTK_WIDGET(win));
225 gtk_window_present (GTK_WINDOW(win));
227 dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
228 gtk_widget_destroy (GTK_WIDGET (wizard));
229 if (gtk_events_pending ())
230 gtk_main_iteration ();
232 if (dialog_response == GTK_RESPONSE_CANCEL) {
235 /* Check whether an account was created: */
236 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
243 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
246 const gchar *authors[] = {
247 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
250 about = gtk_about_dialog_new ();
251 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
252 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
253 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
254 _("Copyright (c) 2006, Nokia Corporation\n"
255 "All rights reserved."));
256 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
257 _("a modest e-mail client\n\n"
258 "design and implementation: Dirk-Jan C. Binnema\n"
259 "contributions from the fine people at KC and Ig\n"
260 "uses the tinymail email framework written by Philip van Hoof"));
261 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
262 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
263 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
264 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
266 gtk_dialog_run (GTK_DIALOG (about));
267 gtk_widget_destroy(about);
271 * Gets the list of currently selected messages. If the win is the
272 * main window, then it returns a newly allocated list of the headers
273 * selected in the header view. If win is the msg view window, then
274 * the value returned is a list with just a single header.
276 * The caller of this funcion must free the list.
279 get_selected_headers (ModestWindow *win)
281 if (MODEST_IS_MAIN_WINDOW(win)) {
282 GtkWidget *header_view;
284 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
285 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
286 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
288 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
289 /* for MsgViewWindows, we simply return a list with one element */
291 TnyList *list = NULL;
293 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
294 if (header != NULL) {
295 list = tny_simple_list_new ();
296 tny_list_prepend (list, G_OBJECT(header));
297 g_object_unref (G_OBJECT(header));
306 static GtkTreeRowReference *
307 get_next_after_selected_headers (ModestHeaderView *header_view)
309 GtkTreeSelection *sel;
310 GList *selected_rows, *node;
312 GtkTreeRowReference *result;
315 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
316 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
317 selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
319 if (selected_rows == NULL)
322 node = g_list_last (selected_rows);
323 path = gtk_tree_path_copy ((GtkTreePath *) node->data);
324 gtk_tree_path_next (path);
326 result = gtk_tree_row_reference_new (model, path);
328 gtk_tree_path_free (path);
329 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
330 g_list_free (selected_rows);
336 headers_action_mark_as_read (TnyHeader *header,
340 TnyHeaderFlags flags;
342 g_return_if_fail (TNY_IS_HEADER(header));
344 flags = tny_header_get_flags (header);
345 if (flags & TNY_HEADER_FLAG_SEEN) return;
346 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
350 headers_action_mark_as_unread (TnyHeader *header,
354 TnyHeaderFlags flags;
356 g_return_if_fail (TNY_IS_HEADER(header));
358 flags = tny_header_get_flags (header);
359 if (flags & TNY_HEADER_FLAG_SEEN) {
360 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
364 /** After deleing a message that is currently visible in a window,
365 * show the next message from the list, or close the window if there are no more messages.
368 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
370 /* Close msg view window or select next */
371 if (!modest_msg_view_window_select_next_message (win) &&
372 !modest_msg_view_window_select_previous_message (win)) {
374 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
380 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
382 TnyList *header_list = NULL;
383 TnyIterator *iter = NULL;
384 TnyHeader *header = NULL;
385 gchar *message = NULL;
388 ModestWindowMgr *mgr;
389 GtkWidget *header_view = NULL;
391 g_return_if_fail (MODEST_IS_WINDOW(win));
393 /* Check first if the header view has the focus */
394 if (MODEST_IS_MAIN_WINDOW (win)) {
396 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
397 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
398 if (!gtk_widget_is_focus (header_view))
402 /* Get the headers, either from the header view (if win is the main window),
403 * or from the message view window: */
404 header_list = get_selected_headers (win);
405 if (!header_list) return;
407 /* Check if any of the headers are already opened, or in the process of being opened */
408 if (MODEST_IS_MAIN_WINDOW (win)) {
409 gint opened_headers = 0;
411 iter = tny_list_create_iterator (header_list);
412 mgr = modest_runtime_get_window_mgr ();
413 while (!tny_iterator_is_done (iter)) {
414 header = TNY_HEADER (tny_iterator_get_current (iter));
416 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
418 g_object_unref (header);
420 tny_iterator_next (iter);
422 g_object_unref (iter);
424 if (opened_headers > 0) {
427 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
430 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
433 g_object_unref (header_list);
439 if (tny_list_get_length(header_list) == 1) {
440 iter = tny_list_create_iterator (header_list);
441 header = TNY_HEADER (tny_iterator_get_current (iter));
443 desc = g_strdup_printf ("%s", tny_header_get_subject (header));
444 g_object_unref (header);
447 g_object_unref (iter);
449 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
450 tny_list_get_length(header_list)), desc);
452 /* Confirmation dialog */
453 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
457 if (response == GTK_RESPONSE_OK) {
458 ModestWindow *main_window = NULL;
459 ModestWindowMgr *mgr = NULL;
460 GtkTreeModel *model = NULL;
461 GtkTreeSelection *sel = NULL;
462 GList *sel_list = NULL, *tmp = NULL;
463 GtkTreeRowReference *next_row_reference = NULL;
464 GtkTreeRowReference *prev_row_reference = NULL;
465 GtkTreePath *next_path = NULL;
466 GtkTreePath *prev_path = NULL;
467 ModestMailOperation *mail_op = NULL;
469 /* Find last selected row */
470 if (MODEST_IS_MAIN_WINDOW (win)) {
471 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
472 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
473 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
474 for (tmp=sel_list; tmp; tmp=tmp->next) {
475 if (tmp->next == NULL) {
476 prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
477 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
479 gtk_tree_path_prev (prev_path);
480 gtk_tree_path_next (next_path);
482 prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
483 next_row_reference = gtk_tree_row_reference_new (model, next_path);
488 /* Disable window dimming management */
489 modest_window_disable_dimming (MODEST_WINDOW(win));
491 /* Remove each header. If it's a view window header_view == NULL */
492 mail_op = modest_mail_operation_new ((GObject *) win);
493 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
495 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
496 g_object_unref (mail_op);
498 /* Enable window dimming management */
500 gtk_tree_selection_unselect_all (sel);
502 modest_window_enable_dimming (MODEST_WINDOW(win));
504 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
505 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
507 /* Get main window */
508 mgr = modest_runtime_get_window_mgr ();
509 main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
511 /* Move cursor to next row */
514 /* Select next or previous row */
515 if (gtk_tree_row_reference_valid (next_row_reference)) {
516 /* next_path = gtk_tree_row_reference_get_path (row_reference); */
517 gtk_tree_selection_select_path (sel, next_path);
519 else if (gtk_tree_row_reference_valid (prev_row_reference)) {
520 gtk_tree_selection_select_path (sel, prev_path);
524 if (next_row_reference != NULL)
525 gtk_tree_row_reference_free (next_row_reference);
526 if (next_path != NULL)
527 gtk_tree_path_free (next_path);
528 if (prev_row_reference != NULL)
529 gtk_tree_row_reference_free (prev_row_reference);
530 if (prev_path != NULL)
531 gtk_tree_path_free (prev_path);
534 /* Update toolbar dimming state */
536 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
539 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
540 g_list_free (sel_list);
546 g_object_unref (header_list);
552 /* delete either message or folder, based on where we are */
554 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
556 g_return_if_fail (MODEST_IS_WINDOW(win));
558 /* Check first if the header view has the focus */
559 if (MODEST_IS_MAIN_WINDOW (win)) {
561 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
562 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
563 if (gtk_widget_is_focus (w)) {
564 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
568 modest_ui_actions_on_delete_message (action, win);
572 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
574 ModestWindowMgr *mgr = NULL;
576 #ifdef MODEST_PLATFORM_MAEMO
577 modest_osso_save_state();
578 #endif /* MODEST_PLATFORM_MAEMO */
580 g_debug ("closing down, clearing %d item(s) from operation queue",
581 modest_mail_operation_queue_num_elements
582 (modest_runtime_get_mail_operation_queue()));
584 /* cancel all outstanding operations */
585 modest_mail_operation_queue_cancel_all
586 (modest_runtime_get_mail_operation_queue());
588 g_debug ("queue has been cleared");
591 /* Check if there are opened editing windows */
592 mgr = modest_runtime_get_window_mgr ();
593 modest_window_mgr_close_all_windows (mgr);
595 /* note: when modest-tny-account-store is finalized,
596 it will automatically set all network connections
599 /* gtk_main_quit (); */
603 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
607 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
609 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
610 /* gtk_widget_destroy (GTK_WIDGET (win)); */
611 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
612 /* gboolean ret_value; */
613 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
614 /* } else if (MODEST_IS_WINDOW (win)) { */
615 /* gtk_widget_destroy (GTK_WIDGET (win)); */
617 /* g_return_if_reached (); */
622 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
624 GtkClipboard *clipboard = NULL;
625 gchar *selection = NULL;
627 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
628 selection = gtk_clipboard_wait_for_text (clipboard);
630 /* Question: why is the clipboard being used here?
631 * It doesn't really make a lot of sense. */
635 modest_address_book_add_address (selection);
641 modest_ui_actions_on_accounts (GtkAction *action,
644 /* This is currently only implemented for Maemo */
645 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
646 if (!modest_ui_actions_run_account_setup_wizard (win))
647 g_debug ("%s: wizard was already running", __FUNCTION__);
651 /* Show the list of accounts */
652 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
653 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
655 /* The accounts dialog must be modal */
656 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
657 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
661 #ifdef MODEST_PLATFORM_MAEMO
663 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
665 /* Save any changes. */
666 modest_connection_specific_smtp_window_save_server_accounts (
667 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
668 gtk_widget_destroy (GTK_WIDGET (window));
674 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
676 /* This is currently only implemented for Maemo,
677 * because it requires an API (libconic) to detect different connection
680 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
682 /* Create the window if necessary: */
683 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
684 modest_connection_specific_smtp_window_fill_with_connections (
685 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
686 modest_runtime_get_account_mgr());
688 /* Show the window: */
689 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
690 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
691 gtk_widget_show (specific_window);
693 /* Save changes when the window is hidden: */
694 g_signal_connect (specific_window, "hide",
695 G_CALLBACK (on_smtp_servers_window_hide), win);
696 #endif /* MODEST_PLATFORM_MAEMO */
700 modest_ui_actions_compose_msg(ModestWindow *win,
703 const gchar *bcc_str,
704 const gchar *subject_str,
705 const gchar *body_str,
707 gboolean set_as_modified)
709 gchar *account_name = NULL;
711 TnyAccount *account = NULL;
712 TnyFolder *folder = NULL;
713 gchar *from_str = NULL, *signature = NULL, *body = NULL;
714 gboolean use_signature = FALSE;
715 ModestWindow *msg_win = NULL;
716 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
717 ModestTnyAccountStore *store = modest_runtime_get_account_store();
719 account_name = modest_account_mgr_get_default_account(mgr);
721 g_printerr ("modest: no account found\n");
724 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
726 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
729 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
731 g_printerr ("modest: failed to find Drafts folder\n");
734 from_str = modest_account_mgr_get_from_string (mgr, account_name);
736 g_printerr ("modest: failed get from string for '%s'\n", account_name);
740 signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
741 if (body_str != NULL) {
742 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
744 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
747 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
749 g_printerr ("modest: failed to create new msg\n");
753 /* Create and register edit window */
754 /* This is destroyed by TODO. */
755 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
756 while (attachments) {
757 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
759 attachments = g_slist_next(attachments);
761 modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
762 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
764 gtk_widget_show_all (GTK_WIDGET (msg_win));
770 g_free (account_name);
771 if (account) g_object_unref (G_OBJECT(account));
772 if (folder) g_object_unref (G_OBJECT(folder));
773 if (msg_win) g_object_unref (G_OBJECT(msg_win));
774 if (msg) g_object_unref (G_OBJECT(msg));
778 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
780 /* if there are no accounts yet, just show the wizard */
781 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
782 if (!modest_ui_actions_run_account_setup_wizard (win))
785 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
790 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
794 ModestMailOperationStatus status;
796 /* If there is no message or the operation was not successful */
797 status = modest_mail_operation_get_status (mail_op);
798 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
800 /* Remove the header from the preregistered uids */
801 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
819 OpenMsgBannerInfo *banner_info;
820 GHashTable *row_refs_per_header;
824 open_msg_banner_idle (gpointer userdata)
826 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
828 gdk_threads_enter ();
829 banner_info->idle_handler = 0;
830 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
831 g_object_ref (banner_info->banner);
833 gdk_threads_leave ();
840 open_msg_cb (ModestMailOperation *mail_op,
847 ModestWindowMgr *mgr = NULL;
848 ModestWindow *parent_win = NULL;
849 ModestWindow *win = NULL;
850 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
851 gchar *account = NULL;
853 gboolean open_in_editor = FALSE;
854 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
856 /* Do nothing if there was any problem with the mail
857 operation. The error will be shown by the error_handler of
858 the mail operation */
859 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
862 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
863 folder = tny_header_get_folder (header);
865 /* Mark header as read */
866 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
868 /* Gets folder type (OUTBOX headers will be opened in edit window */
869 if (modest_tny_folder_is_local_folder (folder)) {
870 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
871 if (folder_type == TNY_FOLDER_TYPE_INVALID)
872 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
876 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
877 TnyTransportAccount *traccount = NULL;
878 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
879 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
881 ModestTnySendQueue *send_queue = NULL;
882 ModestTnySendQueueStatus status;
884 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
885 TNY_ACCOUNT(traccount)));
886 send_queue = modest_runtime_get_send_queue(traccount);
887 msg_id = modest_tny_send_queue_get_msg_id (header);
888 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
889 /* Only open messages in outbox with the editor if they are in Failed state */
890 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
891 open_in_editor = TRUE;
894 g_object_unref(traccount);
896 g_warning("Cannot get transport account for message in outbox!!");
898 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
899 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
904 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
906 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
908 if (open_in_editor) {
909 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
910 const gchar *from_header = NULL;
912 from_header = tny_header_get_from (header);
914 /* we cannot edit without a valid account... */
915 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
916 if (!modest_ui_actions_run_account_setup_wizard(parent_win))
921 GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
923 for (node = accounts; node != NULL; node = g_slist_next (node)) {
924 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
926 if (from && (strcmp (from_header, from) == 0)) {
928 account = g_strdup (node->data);
934 g_slist_foreach (accounts, (GFunc) g_free, NULL);
935 g_slist_free (accounts);
938 win = modest_msg_edit_window_new (msg, account, TRUE);
943 gchar *uid = modest_tny_folder_get_header_unique_id (header);
945 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
946 GtkTreeRowReference *row_reference;
948 row_reference = (GtkTreeRowReference *) g_hash_table_lookup (helper->row_refs_per_header, header);
950 win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
951 helper->model, row_reference);
953 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
958 /* Register and show new window */
960 mgr = modest_runtime_get_window_mgr ();
961 modest_window_mgr_register_window (mgr, win);
962 g_object_unref (win);
963 gtk_widget_show_all (GTK_WIDGET(win));
966 /* Update toolbar dimming state */
967 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
968 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
974 g_object_unref (parent_win);
975 g_object_unref (folder);
979 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
984 ModestMailOperationStatus status;
986 win = modest_mail_operation_get_source (mail_op);
987 error = modest_mail_operation_get_error (mail_op);
988 status = modest_mail_operation_get_status (mail_op);
990 /* If the mail op has been cancelled then it's not an error:
991 don't show any message */
992 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
994 if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
995 error->code == TNY_IO_ERROR_WRITE ||
996 error->code == TNY_IO_ERROR_READ) {
997 modest_platform_information_banner ((GtkWidget *) win,
998 NULL, dgettext("ke-recv",
999 "cerm_device_memory_full"));
1000 } else if (user_data) {
1001 modest_platform_information_banner ((GtkWidget *) win,
1007 g_object_unref (win);
1011 * Returns the account a list of headers belongs to. It returns a
1012 * *new* reference so don't forget to unref it
1015 get_account_from_header_list (TnyList *headers)
1017 TnyAccount *account = NULL;
1019 if (tny_list_get_length (headers) > 0) {
1020 TnyIterator *iter = tny_list_create_iterator (headers);
1021 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1022 TnyFolder *folder = tny_header_get_folder (header);
1025 g_object_unref (header);
1027 while (!tny_iterator_is_done (iter)) {
1028 header = TNY_HEADER (tny_iterator_get_current (iter));
1029 folder = tny_header_get_folder (header);
1032 g_object_unref (header);
1034 tny_iterator_next (iter);
1039 account = tny_folder_get_account (folder);
1040 g_object_unref (folder);
1044 g_object_unref (header);
1046 g_object_unref (iter);
1052 foreach_unregister_headers (gpointer data,
1055 ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1056 TnyHeader *header = TNY_HEADER (data);
1058 modest_window_mgr_unregister_header (mgr, header);
1062 open_msgs_helper_destroyer (gpointer user_data)
1064 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1066 if (helper->banner_info) {
1067 g_free (helper->banner_info->message);
1068 if (helper->banner_info->idle_handler > 0) {
1069 g_source_remove (helper->banner_info->idle_handler);
1070 helper->banner_info->idle_handler = 0;
1072 if (helper->banner_info->banner != NULL) {
1073 gtk_widget_destroy (helper->banner_info->banner);
1074 g_object_unref (helper->banner_info->banner);
1075 helper->banner_info->banner = NULL;
1077 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1078 helper->banner_info = NULL;
1080 g_object_unref (helper->model);
1081 g_object_unref (helper->headers);
1082 g_hash_table_destroy (helper->row_refs_per_header);
1083 g_slice_free (OpenMsgHelper, helper);
1087 open_msgs_performer(gboolean canceled,
1089 GtkWindow *parent_window,
1090 TnyAccount *account,
1093 ModestMailOperation *mail_op = NULL;
1094 const gchar *proto_name;
1096 ModestTransportStoreProtocol proto;
1097 TnyList *not_opened_headers;
1098 TnyConnectionStatus status;
1099 gboolean show_open_draft = FALSE;
1100 OpenMsgHelper *helper = NULL;
1102 helper = (OpenMsgHelper *) user_data;
1103 not_opened_headers = helper->headers;
1105 status = tny_account_get_connection_status (account);
1106 if (err || canceled) {
1107 /* Unregister the already registered headers */
1108 tny_list_foreach (not_opened_headers, foreach_unregister_headers,
1109 modest_runtime_get_window_mgr ());
1110 /* Free the helper */
1111 open_msgs_helper_destroyer (helper);
1115 /* Get the error message depending on the protocol */
1116 proto_name = tny_account_get_proto (account);
1117 if (proto_name != NULL) {
1118 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1120 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1123 /* Create the error messages */
1124 if (tny_list_get_length (not_opened_headers) == 1) {
1125 if (proto == MODEST_PROTOCOL_STORE_POP) {
1126 error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1127 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1128 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1129 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1130 error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1131 tny_header_get_subject (header));
1132 g_object_unref (header);
1133 g_object_unref (iter);
1138 TnyFolderType folder_type;
1140 iter = tny_list_create_iterator (not_opened_headers);
1141 header = TNY_HEADER (tny_iterator_get_current (iter));
1142 folder = tny_header_get_folder (header);
1143 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1144 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1145 g_object_unref (folder);
1146 g_object_unref (header);
1147 g_object_unref (iter);
1148 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1151 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1154 /* Create the mail operation */
1156 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1157 modest_ui_actions_disk_operations_error_handler,
1159 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1162 if (show_open_draft) {
1163 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1164 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1165 helper->banner_info->banner = NULL;
1166 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1167 helper->banner_info);
1170 modest_mail_operation_get_msgs_full (mail_op,
1174 open_msgs_helper_destroyer);
1179 g_object_unref (mail_op);
1180 g_object_unref (account);
1184 * This function is used by both modest_ui_actions_on_open and
1185 * modest_ui_actions_on_header_activated. This way we always do the
1186 * same when trying to open messages.
1189 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1191 ModestWindowMgr *mgr = NULL;
1192 TnyIterator *iter = NULL, *iter_not_opened = NULL;
1193 TnyList *not_opened_headers = NULL;
1194 TnyHeaderFlags flags = 0;
1195 TnyAccount *account;
1196 gint uncached_msgs = 0;
1197 GtkWidget *header_view;
1198 GtkTreeModel *model;
1199 GHashTable *refs_for_headers;
1200 OpenMsgHelper *helper;
1201 GtkTreeSelection *sel;
1202 GList *sel_list = NULL, *sel_list_iter = NULL;
1204 g_return_if_fail (headers != NULL);
1206 /* Check that only one message is selected for opening */
1207 if (tny_list_get_length (headers) != 1) {
1208 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1209 NULL, _("mcen_ib_select_one_message"));
1213 mgr = modest_runtime_get_window_mgr ();
1214 iter = tny_list_create_iterator (headers);
1216 /* Get the account */
1217 account = get_account_from_header_list (headers);
1222 /* Get the selections, we need to get the references to the
1223 rows here because the treeview/model could dissapear (the
1224 user might want to select another folder)*/
1225 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1226 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1227 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1228 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
1229 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1230 refs_for_headers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1231 (GDestroyNotify) gtk_tree_row_reference_free);
1233 /* Look if we already have a message view for each header. If
1234 true, then remove the header from the list of headers to
1236 sel_list_iter = sel_list;
1237 not_opened_headers = tny_simple_list_new ();
1238 while (!tny_iterator_is_done (iter) && sel_list_iter) {
1240 ModestWindow *window = NULL;
1241 TnyHeader *header = NULL;
1242 gboolean found = FALSE;
1244 header = TNY_HEADER (tny_iterator_get_current (iter));
1246 flags = tny_header_get_flags (header);
1249 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1251 /* Do not open again the message and present the
1252 window to the user */
1255 gtk_window_present (GTK_WINDOW (window));
1257 /* the header has been registered already, we don't do
1258 * anything but wait for the window to come up*/
1259 g_debug ("header %p already registered, waiting for window", header);
1262 GtkTreeRowReference *row_reference;
1264 tny_list_append (not_opened_headers, G_OBJECT (header));
1265 /* Create a new row reference and add it to the hash table */
1266 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list_iter->data);
1267 g_hash_table_insert (refs_for_headers, header, row_reference);
1271 g_object_unref (header);
1274 tny_iterator_next (iter);
1275 sel_list_iter = g_list_next (sel_list_iter);
1277 g_object_unref (iter);
1279 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1280 g_list_free (sel_list);
1282 /* Open each message */
1283 if (tny_list_get_length (not_opened_headers) == 0) {
1284 g_hash_table_destroy (refs_for_headers);
1288 /* If some messages would have to be downloaded, ask the user to
1289 * make a connection. It's generally easier to do this here (in the mainloop)
1290 * than later in a thread:
1292 if (tny_list_get_length (not_opened_headers) > 0) {
1293 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1295 if (uncached_msgs > 0) {
1296 /* Allways download if we are online. */
1297 if (!tny_device_is_online (modest_runtime_get_device ())) {
1300 /* If ask for user permission to download the messages */
1301 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1302 ngettext("mcen_nc_get_msg",
1306 /* End if the user does not want to continue */
1307 if (response == GTK_RESPONSE_CANCEL) {
1308 g_hash_table_destroy (refs_for_headers);
1315 /* Register the headers before actually creating the windows: */
1316 iter_not_opened = tny_list_create_iterator (not_opened_headers);
1317 while (!tny_iterator_is_done (iter_not_opened)) {
1318 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1320 modest_window_mgr_register_header (mgr, header, NULL);
1321 g_object_unref (header);
1323 tny_iterator_next (iter_not_opened);
1325 g_object_unref (iter_not_opened);
1326 iter_not_opened = NULL;
1328 /* Create the helper. We need to get a reference to the model
1329 here because it could change while the message is readed
1330 (the user could switch between folders) */
1331 helper = g_slice_new (OpenMsgHelper);
1332 helper->model = g_object_ref (model);
1333 helper->headers = g_object_ref (not_opened_headers);
1334 helper->row_refs_per_header = refs_for_headers;
1335 helper->banner_info = NULL;
1337 /* Connect to the account and perform */
1338 if (uncached_msgs > 0) {
1339 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1340 open_msgs_performer, helper);
1342 /* Call directly the performer, do not need to connect */
1343 open_msgs_performer (FALSE, NULL, (GtkWindow *) win,
1344 g_object_ref (account), helper);
1349 g_object_unref (account);
1350 if (not_opened_headers)
1351 g_object_unref (not_opened_headers);
1355 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1360 headers = get_selected_headers (win);
1365 open_msgs_from_headers (headers, win);
1367 g_object_unref(headers);
1372 free_reply_forward_helper (gpointer data)
1374 ReplyForwardHelper *helper;
1376 helper = (ReplyForwardHelper *) data;
1377 g_free (helper->account_name);
1378 g_slice_free (ReplyForwardHelper, helper);
1382 reply_forward_cb (ModestMailOperation *mail_op,
1390 ReplyForwardHelper *rf_helper;
1391 ModestWindow *msg_win = NULL;
1392 ModestEditType edit_type;
1394 TnyAccount *account = NULL;
1395 ModestWindowMgr *mgr = NULL;
1396 gchar *signature = NULL;
1397 gboolean use_signature;
1399 /* If there was any error. The mail operation could be NULL,
1400 this means that we already have the message downloaded and
1401 that we didn't do a mail operation to retrieve it */
1402 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1405 g_return_if_fail (user_data != NULL);
1406 rf_helper = (ReplyForwardHelper *) user_data;
1408 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1409 rf_helper->account_name);
1410 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(),
1411 rf_helper->account_name,
1414 /* Create reply mail */
1415 switch (rf_helper->action) {
1418 modest_tny_msg_create_reply_msg (msg, header, from,
1419 (use_signature) ? signature : NULL,
1420 rf_helper->reply_forward_type,
1421 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1423 case ACTION_REPLY_TO_ALL:
1425 modest_tny_msg_create_reply_msg (msg, header, from,
1426 (use_signature) ? signature : NULL,
1427 rf_helper->reply_forward_type,
1428 MODEST_TNY_MSG_REPLY_MODE_ALL);
1429 edit_type = MODEST_EDIT_TYPE_REPLY;
1431 case ACTION_FORWARD:
1433 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1434 rf_helper->reply_forward_type);
1435 edit_type = MODEST_EDIT_TYPE_FORWARD;
1438 g_return_if_reached ();
1445 g_printerr ("modest: failed to create message\n");
1449 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1450 rf_helper->account_name,
1451 TNY_ACCOUNT_TYPE_STORE);
1453 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1457 /* Create and register the windows */
1458 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1459 mgr = modest_runtime_get_window_mgr ();
1460 modest_window_mgr_register_window (mgr, msg_win);
1462 if (rf_helper->parent_window != NULL) {
1463 gdouble parent_zoom;
1465 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1466 modest_window_set_zoom (msg_win, parent_zoom);
1469 /* Show edit window */
1470 gtk_widget_show_all (GTK_WIDGET (msg_win));
1474 g_object_unref (msg_win);
1476 g_object_unref (G_OBJECT (new_msg));
1478 g_object_unref (G_OBJECT (account));
1479 /* g_object_unref (msg); */
1480 free_reply_forward_helper (rf_helper);
1483 /* Checks a list of headers. If any of them are not currently
1484 * downloaded (CACHED) then returns TRUE else returns FALSE.
1487 header_list_count_uncached_msgs (TnyList *header_list)
1490 gint uncached_messages = 0;
1492 iter = tny_list_create_iterator (header_list);
1493 while (!tny_iterator_is_done (iter)) {
1496 header = TNY_HEADER (tny_iterator_get_current (iter));
1498 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1499 uncached_messages ++;
1500 g_object_unref (header);
1503 tny_iterator_next (iter);
1505 g_object_unref (iter);
1507 return uncached_messages;
1510 /* Returns FALSE if the user does not want to download the
1511 * messages. Returns TRUE if the user allowed the download.
1514 connect_to_get_msg (ModestWindow *win,
1515 gint num_of_uncached_msgs,
1516 TnyAccount *account)
1518 GtkResponseType response;
1520 /* Allways download if we are online. */
1521 if (tny_device_is_online (modest_runtime_get_device ()))
1524 /* If offline, then ask for user permission to download the messages */
1525 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1526 ngettext("mcen_nc_get_msg",
1528 num_of_uncached_msgs));
1530 if (response == GTK_RESPONSE_CANCEL)
1533 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1537 * Common code for the reply and forward actions
1540 reply_forward (ReplyForwardAction action, ModestWindow *win)
1542 ModestMailOperation *mail_op = NULL;
1543 TnyList *header_list = NULL;
1544 ReplyForwardHelper *rf_helper = NULL;
1545 guint reply_forward_type;
1546 gboolean continue_download = TRUE;
1547 gboolean do_retrieve = TRUE;
1549 g_return_if_fail (MODEST_IS_WINDOW(win));
1551 /* we need an account when editing */
1552 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1553 if (!modest_ui_actions_run_account_setup_wizard (win))
1557 header_list = get_selected_headers (win);
1561 reply_forward_type =
1562 modest_conf_get_int (modest_runtime_get_conf (),
1563 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1566 /* check if we need to download msg before asking about it */
1567 do_retrieve = (action == ACTION_FORWARD) ||
1568 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1571 gint num_of_unc_msgs;
1573 /* check that the messages have been previously downloaded */
1574 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1575 /* If there are any uncached message ask the user
1576 * whether he/she wants to download them. */
1577 if (num_of_unc_msgs) {
1578 TnyAccount *account = get_account_from_header_list (header_list);
1580 continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1581 g_object_unref (account);
1586 if (!continue_download) {
1587 g_object_unref (header_list);
1591 /* We assume that we can only select messages of the
1592 same folder and that we reply all of them from the
1593 same account. In fact the interface currently only
1594 allows single selection */
1597 rf_helper = g_slice_new0 (ReplyForwardHelper);
1598 rf_helper->reply_forward_type = reply_forward_type;
1599 rf_helper->action = action;
1600 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1602 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1603 rf_helper->parent_window = GTK_WIDGET (win);
1604 if (!rf_helper->account_name)
1605 rf_helper->account_name =
1606 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1608 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1611 /* Get header and message. Do not free them here, the
1612 reply_forward_cb must do it */
1613 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1614 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1615 if (!msg || !header) {
1617 g_object_unref (msg);
1618 g_printerr ("modest: no message found\n");
1621 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1624 g_object_unref (header);
1629 /* Only reply/forward to one message */
1630 iter = tny_list_create_iterator (header_list);
1631 header = TNY_HEADER (tny_iterator_get_current (iter));
1632 g_object_unref (iter);
1635 /* Retrieve messages */
1638 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1639 modest_ui_actions_disk_operations_error_handler,
1641 modest_mail_operation_queue_add (
1642 modest_runtime_get_mail_operation_queue (), mail_op);
1644 modest_mail_operation_get_msg (mail_op,
1649 g_object_unref(mail_op);
1651 /* we put a ref here to prevent double unref as the reply
1652 * forward callback unrefs the header at its end */
1653 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1657 g_object_unref (header);
1663 g_object_unref (header_list);
1667 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1669 g_return_if_fail (MODEST_IS_WINDOW(win));
1671 reply_forward (ACTION_REPLY, win);
1675 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1677 g_return_if_fail (MODEST_IS_WINDOW(win));
1679 reply_forward (ACTION_FORWARD, win);
1683 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1685 g_return_if_fail (MODEST_IS_WINDOW(win));
1687 reply_forward (ACTION_REPLY_TO_ALL, win);
1691 modest_ui_actions_on_next (GtkAction *action,
1692 ModestWindow *window)
1694 if (MODEST_IS_MAIN_WINDOW (window)) {
1695 GtkWidget *header_view;
1697 header_view = modest_main_window_get_child_widget (
1698 MODEST_MAIN_WINDOW(window),
1699 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1703 modest_header_view_select_next (
1704 MODEST_HEADER_VIEW(header_view));
1705 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1706 modest_msg_view_window_select_next_message (
1707 MODEST_MSG_VIEW_WINDOW (window));
1709 g_return_if_reached ();
1714 modest_ui_actions_on_prev (GtkAction *action,
1715 ModestWindow *window)
1717 g_return_if_fail (MODEST_IS_WINDOW(window));
1719 if (MODEST_IS_MAIN_WINDOW (window)) {
1720 GtkWidget *header_view;
1721 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1722 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1726 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1727 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1728 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1730 g_return_if_reached ();
1735 modest_ui_actions_on_sort (GtkAction *action,
1736 ModestWindow *window)
1738 g_return_if_fail (MODEST_IS_WINDOW(window));
1740 if (MODEST_IS_MAIN_WINDOW (window)) {
1741 GtkWidget *header_view;
1742 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1743 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1745 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1750 /* Show sorting dialog */
1751 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1756 new_messages_arrived (ModestMailOperation *self,
1757 TnyList *new_headers,
1761 gboolean show_visual_notifications;
1763 source = modest_mail_operation_get_source (self);
1764 show_visual_notifications = (source) ? FALSE : TRUE;
1766 g_object_unref (source);
1768 /* Notify new messages have been downloaded. If the
1769 send&receive was invoked by the user then do not show any
1770 visual notification, only play a sound and activate the LED
1771 (for the Maemo version) */
1772 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1773 modest_platform_on_new_headers_received (new_headers,
1774 show_visual_notifications);
1779 retrieve_all_messages_cb (GObject *source,
1781 guint retrieve_limit)
1787 window = GTK_WINDOW (source);
1788 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
1789 num_msgs, retrieve_limit);
1791 /* Ask the user if they want to retrieve all the messages */
1793 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1794 _("mcen_bd_get_all"),
1795 _("mcen_bd_newest_only"));
1796 /* Free and return */
1798 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1802 TnyAccount *account;
1804 gchar *account_name;
1805 gboolean poke_status;
1806 gboolean interactive;
1810 do_send_receive_performer (gboolean canceled,
1812 GtkWindow *parent_window,
1813 TnyAccount *account,
1816 ModestMailOperation *mail_op;
1817 SendReceiveInfo *info;
1819 info = (SendReceiveInfo *) user_data;
1821 if (err || canceled) {
1825 /* Set send/receive operation in progress */
1826 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1827 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1830 mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1831 modest_ui_actions_send_receive_error_handler,
1834 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1835 g_signal_connect (G_OBJECT(mail_op), "operation-finished",
1836 G_CALLBACK (on_send_receive_finished),
1839 /* Send & receive. */
1840 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1841 modest_mail_operation_update_account (mail_op, info->account_name, info->poke_status, info->interactive,
1842 (info->win) ? retrieve_all_messages_cb : NULL,
1843 new_messages_arrived, info->win);
1844 g_object_unref (G_OBJECT (mail_op));
1848 if (info->account_name)
1849 g_free (info->account_name);
1851 g_object_unref (info->win);
1853 g_object_unref (info->account);
1854 g_slice_free (SendReceiveInfo, info);
1858 * This function performs the send & receive required actions. The
1859 * window is used to create the mail operation. Typically it should
1860 * always be the main window, but we pass it as argument in order to
1864 modest_ui_actions_do_send_receive (const gchar *account_name,
1865 gboolean force_connection,
1866 gboolean poke_status,
1867 gboolean interactive,
1870 gchar *acc_name = NULL;
1871 SendReceiveInfo *info;
1872 ModestTnyAccountStore *acc_store;
1874 /* If no account name was provided then get the current account, and if
1875 there is no current account then pick the default one: */
1876 if (!account_name) {
1878 acc_name = g_strdup (modest_window_get_active_account (win));
1880 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1882 g_printerr ("modest: cannot get default account\n");
1886 acc_name = g_strdup (account_name);
1889 acc_store = modest_runtime_get_account_store ();
1891 /* Create the info for the connect and perform */
1892 info = g_slice_new (SendReceiveInfo);
1893 info->account_name = acc_name;
1894 info->win = (win) ? g_object_ref (win) : NULL;
1895 info->poke_status = poke_status;
1896 info->interactive = interactive;
1897 info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1898 TNY_ACCOUNT_TYPE_STORE);
1900 /* Invoke the connect and perform */
1901 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
1902 force_connection, info->account,
1903 do_send_receive_performer, info);
1908 modest_ui_actions_do_cancel_send (const gchar *account_name,
1911 TnyTransportAccount *transport_account;
1912 TnySendQueue *send_queue = NULL;
1913 GError *error = NULL;
1915 /* Get transport account */
1917 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1918 (modest_runtime_get_account_store(),
1920 TNY_ACCOUNT_TYPE_TRANSPORT));
1921 if (!transport_account) {
1922 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1927 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1928 if (!TNY_IS_SEND_QUEUE(send_queue)) {
1929 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1930 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1931 "modest: could not find send queue for account\n");
1933 /* Cancel the current send */
1934 tny_account_cancel (TNY_ACCOUNT (transport_account));
1936 /* Suspend all pending messages */
1937 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
1941 if (transport_account != NULL)
1942 g_object_unref (G_OBJECT (transport_account));
1946 modest_ui_actions_cancel_send_all (ModestWindow *win)
1948 GSList *account_names, *iter;
1950 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1953 iter = account_names;
1955 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1956 iter = g_slist_next (iter);
1959 modest_account_mgr_free_account_names (account_names);
1960 account_names = NULL;
1964 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
1967 /* Check if accounts exist */
1968 gboolean accounts_exist =
1969 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1971 /* If not, allow the user to create an account before trying to send/receive. */
1972 if (!accounts_exist)
1973 modest_ui_actions_on_accounts (NULL, win);
1975 /* Cancel all sending operaitons */
1976 modest_ui_actions_cancel_send_all (win);
1980 * Refreshes all accounts. This function will be used by automatic
1984 modest_ui_actions_do_send_receive_all (ModestWindow *win,
1985 gboolean force_connection,
1986 gboolean poke_status,
1987 gboolean interactive)
1989 GSList *account_names, *iter;
1991 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1994 iter = account_names;
1996 modest_ui_actions_do_send_receive ((const char*) iter->data,
1998 poke_status, interactive, win);
1999 iter = g_slist_next (iter);
2002 modest_account_mgr_free_account_names (account_names);
2003 account_names = NULL;
2007 * Handler of the click on Send&Receive button in the main toolbar
2010 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2012 /* Check if accounts exist */
2013 gboolean accounts_exist;
2016 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2018 /* If not, allow the user to create an account before trying to send/receive. */
2019 if (!accounts_exist)
2020 modest_ui_actions_on_accounts (NULL, win);
2022 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2023 if (MODEST_IS_MAIN_WINDOW (win)) {
2024 GtkWidget *folder_view;
2025 TnyFolderStore *folder_store;
2028 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2029 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2033 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2036 g_object_unref (folder_store);
2039 /* Refresh the active account. Force the connection if needed
2040 and poke the status of all folders */
2041 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2046 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2049 GtkWidget *header_view;
2051 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2053 header_view = modest_main_window_get_child_widget (main_window,
2054 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2058 conf = modest_runtime_get_conf ();
2060 /* what is saved/restored is depending on the style; thus; we save with
2061 * old style, then update the style, and restore for this new style
2063 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2065 if (modest_header_view_get_style
2066 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2067 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2068 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2070 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2071 MODEST_HEADER_VIEW_STYLE_DETAILS);
2073 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2074 MODEST_CONF_HEADER_VIEW_KEY);
2079 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2081 ModestMainWindow *main_window)
2083 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2084 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2086 /* in the case the folder is empty, show the empty folder message and focus
2088 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2089 if (modest_header_view_is_empty (header_view)) {
2090 TnyFolder *folder = modest_header_view_get_folder (header_view);
2091 GtkWidget *folder_view =
2092 modest_main_window_get_child_widget (main_window,
2093 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2095 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2096 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2100 /* If no header has been selected then exit */
2105 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2106 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2108 /* Update toolbar dimming state */
2109 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2110 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2114 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2116 ModestMainWindow *main_window)
2120 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2125 if (modest_header_view_count_selected_headers (header_view) > 1) {
2126 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2131 /* headers = tny_simple_list_new (); */
2132 /* tny_list_prepend (headers, G_OBJECT (header)); */
2133 headers = modest_header_view_get_selected_headers (header_view);
2135 open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2137 g_object_unref (headers);
2141 set_active_account_from_tny_account (TnyAccount *account,
2142 ModestWindow *window)
2144 const gchar *server_acc_name = tny_account_get_id (account);
2146 /* We need the TnyAccount provided by the
2147 account store because that is the one that
2148 knows the name of the Modest account */
2149 TnyAccount *modest_server_account = modest_server_account =
2150 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2151 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2153 if (!modest_server_account) {
2154 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2158 /* Update active account, but only if it's not a pseudo-account */
2159 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2160 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2161 const gchar *modest_acc_name =
2162 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2163 if (modest_acc_name)
2164 modest_window_set_active_account (window, modest_acc_name);
2167 g_object_unref (modest_server_account);
2172 folder_refreshed_cb (ModestMailOperation *mail_op,
2176 ModestMainWindow *win = NULL;
2177 GtkWidget *header_view;
2179 g_return_if_fail (TNY_IS_FOLDER (folder));
2181 win = MODEST_MAIN_WINDOW (user_data);
2183 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2186 TnyFolder *current_folder;
2188 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2189 if (current_folder != NULL && folder != current_folder) {
2190 g_object_unref (current_folder);
2192 } else if (current_folder)
2193 g_object_unref (current_folder);
2196 /* Check if folder is empty and set headers view contents style */
2197 if (tny_folder_get_all_count (folder) == 0)
2198 modest_main_window_set_contents_style (win,
2199 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2203 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2204 TnyFolderStore *folder_store,
2206 ModestMainWindow *main_window)
2209 GtkWidget *header_view;
2211 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2213 header_view = modest_main_window_get_child_widget(main_window,
2214 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2218 conf = modest_runtime_get_conf ();
2220 if (TNY_IS_ACCOUNT (folder_store)) {
2222 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2224 /* Show account details */
2225 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2228 if (TNY_IS_FOLDER (folder_store) && selected) {
2230 /* Update the active account */
2231 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2233 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2234 g_object_unref (account);
2238 /* Set the header style by default, it could
2239 be changed later by the refresh callback to
2241 modest_main_window_set_contents_style (main_window,
2242 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2244 /* Set folder on header view. This function
2245 will call tny_folder_refresh_async so we
2246 pass a callback that will be called when
2247 finished. We use that callback to set the
2248 empty view if there are no messages */
2249 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2250 TNY_FOLDER (folder_store),
2251 folder_refreshed_cb,
2254 /* Restore configuration. We need to do this
2255 *after* the set_folder because the widget
2256 memory asks the header view about its
2258 modest_widget_memory_restore (modest_runtime_get_conf (),
2259 G_OBJECT(header_view),
2260 MODEST_CONF_HEADER_VIEW_KEY);
2262 /* Update the active account */
2263 //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2264 /* Save only if we're seeing headers */
2265 if (modest_main_window_get_contents_style (main_window) ==
2266 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2267 modest_widget_memory_save (conf, G_OBJECT (header_view),
2268 MODEST_CONF_HEADER_VIEW_KEY);
2269 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2273 /* Update toolbar dimming state */
2274 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2278 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2285 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2287 online = tny_device_is_online (modest_runtime_get_device());
2290 /* already online -- the item is simply not there... */
2291 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2293 GTK_MESSAGE_WARNING,
2295 _("The %s you selected cannot be found"),
2297 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2298 gtk_dialog_run (GTK_DIALOG(dialog));
2300 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2303 _("mcen_bd_dialog_cancel"),
2304 GTK_RESPONSE_REJECT,
2305 _("mcen_bd_dialog_ok"),
2306 GTK_RESPONSE_ACCEPT,
2308 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2309 "Do you want to get online?"), item);
2310 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2311 gtk_label_new (txt), FALSE, FALSE, 0);
2312 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2315 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2316 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2317 /* TODO: Comment about why is this commented out: */
2318 /* modest_platform_connect_and_wait (); */
2321 gtk_widget_destroy (dialog);
2325 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2328 /* g_message ("%s %s", __FUNCTION__, link); */
2333 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2336 modest_platform_activate_uri (link);
2340 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2343 modest_platform_show_uri_popup (link);
2347 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2350 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2354 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2355 const gchar *address,
2358 /* g_message ("%s %s", __FUNCTION__, address); */
2362 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2363 TnyMsg *saved_draft,
2366 ModestMsgEditWindow *edit_window;
2367 ModestMainWindow *win;
2369 /* FIXME. Make the header view sensitive again. This is a
2370 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2372 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2373 modest_runtime_get_window_mgr(), FALSE));
2375 GtkWidget *hdrview = modest_main_window_get_child_widget(
2376 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2377 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2380 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2382 /* Set draft is there was no error */
2383 if (!modest_mail_operation_get_error (mail_op))
2384 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2386 g_object_unref(edit_window);
2390 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2392 TnyTransportAccount *transport_account;
2393 ModestMailOperation *mail_operation;
2395 gchar *account_name, *from;
2396 ModestAccountMgr *account_mgr;
2397 /* char *info_text; */
2398 gboolean had_error = FALSE;
2399 guint64 available_disk, expected_size;
2402 ModestMainWindow *win;
2404 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2406 data = modest_msg_edit_window_get_msg_data (edit_window);
2409 available_disk = modest_folder_available_space (NULL);
2410 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2411 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2416 if ((available_disk != -1) && expected_size > available_disk) {
2417 modest_msg_edit_window_free_msg_data (edit_window, data);
2419 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2423 account_name = g_strdup (data->account_name);
2424 account_mgr = modest_runtime_get_account_mgr();
2426 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2428 account_name = modest_account_mgr_get_default_account (account_mgr);
2429 if (!account_name) {
2430 g_printerr ("modest: no account found\n");
2431 modest_msg_edit_window_free_msg_data (edit_window, data);
2435 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2436 account_name = g_strdup (data->account_name);
2440 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2441 (modest_runtime_get_account_store(),
2443 TNY_ACCOUNT_TYPE_TRANSPORT));
2444 if (!transport_account) {
2445 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2446 g_free (account_name);
2447 modest_msg_edit_window_free_msg_data (edit_window, data);
2450 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2452 /* Create the mail operation */
2453 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2455 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2457 modest_mail_operation_save_to_drafts (mail_operation,
2469 data->priority_flags,
2470 on_save_to_drafts_cb,
2471 g_object_ref(edit_window));
2473 /* Use the main window as the parent of the banner, if the
2474 main window does not exist it won't be shown, if the parent
2475 window exists then it's properly shown. We don't use the
2476 editor window because it could be closed (save to drafts
2477 could happen after closing the window */
2478 win = (ModestMainWindow *)
2479 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2481 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2482 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2485 modest_msg_edit_window_set_modified (edit_window, FALSE);
2489 g_free (account_name);
2490 g_object_unref (G_OBJECT (transport_account));
2491 g_object_unref (G_OBJECT (mail_operation));
2493 modest_msg_edit_window_free_msg_data (edit_window, data);
2496 * If the drafts folder is selected then make the header view
2497 * insensitive while the message is being saved to drafts
2498 * (it'll be sensitive again in on_save_to_drafts_cb()). This
2499 * is not very clean but it avoids letting the drafts folder
2500 * in an inconsistent state: the user could edit the message
2501 * being saved and undesirable things would happen.
2502 * In the average case the user won't notice anything at
2503 * all. In the worst case (the user is editing a really big
2504 * file from Drafts) the header view will be insensitive
2505 * during the saving process (10 or 20 seconds, depending on
2506 * the message). Anyway this is just a quick workaround: once
2507 * we find a better solution it should be removed
2508 * See NB#65125 (commend #18) for details.
2510 if (!had_error && win != NULL) {
2511 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2512 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2514 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2516 if (modest_tny_folder_is_local_folder(folder)) {
2517 TnyFolderType folder_type;
2518 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2519 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2520 GtkWidget *hdrview = modest_main_window_get_child_widget(
2521 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2522 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2526 if (folder != NULL) g_object_unref(folder);
2533 /* For instance, when clicking the Send toolbar button when editing a message: */
2535 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2537 TnyTransportAccount *transport_account = NULL;
2538 gboolean had_error = FALSE;
2539 guint64 available_disk, expected_size;
2543 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2545 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2548 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2551 available_disk = modest_folder_available_space (NULL);
2552 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2553 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2558 if ((available_disk != -1) && expected_size > available_disk) {
2559 modest_msg_edit_window_free_msg_data (edit_window, data);
2561 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2565 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2566 gchar *account_name = g_strdup (data->account_name);
2568 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2571 account_name = modest_account_mgr_get_default_account (account_mgr);
2573 if (!account_name) {
2574 modest_msg_edit_window_free_msg_data (edit_window, data);
2575 /* Run account setup wizard */
2576 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2581 /* Get the currently-active transport account for this modest account: */
2582 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2583 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2584 (modest_runtime_get_account_store(),
2585 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2588 if (!transport_account) {
2589 modest_msg_edit_window_free_msg_data (edit_window, data);
2590 /* Run account setup wizard */
2591 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2595 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2597 /* Create the mail operation */
2598 ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2599 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2601 modest_mail_operation_send_new_mail (mail_operation,
2613 data->priority_flags);
2615 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2616 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2619 if (modest_mail_operation_get_error (mail_operation) != NULL) {
2620 const GError *error = modest_mail_operation_get_error (mail_operation);
2621 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2622 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2623 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2630 g_free (account_name);
2631 g_object_unref (G_OBJECT (transport_account));
2632 g_object_unref (G_OBJECT (mail_operation));
2634 modest_msg_edit_window_free_msg_data (edit_window, data);
2637 modest_msg_edit_window_set_sent (edit_window, TRUE);
2639 /* Save settings and close the window: */
2640 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2647 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2648 ModestMsgEditWindow *window)
2650 ModestMsgEditFormatState *format_state = NULL;
2652 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2653 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2655 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2658 format_state = modest_msg_edit_window_get_format_state (window);
2659 g_return_if_fail (format_state != NULL);
2661 format_state->bold = gtk_toggle_action_get_active (action);
2662 modest_msg_edit_window_set_format_state (window, format_state);
2663 g_free (format_state);
2668 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2669 ModestMsgEditWindow *window)
2671 ModestMsgEditFormatState *format_state = NULL;
2673 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2674 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2676 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2679 format_state = modest_msg_edit_window_get_format_state (window);
2680 g_return_if_fail (format_state != NULL);
2682 format_state->italics = gtk_toggle_action_get_active (action);
2683 modest_msg_edit_window_set_format_state (window, format_state);
2684 g_free (format_state);
2689 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2690 ModestMsgEditWindow *window)
2692 ModestMsgEditFormatState *format_state = NULL;
2694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2695 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2697 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2700 format_state = modest_msg_edit_window_get_format_state (window);
2701 g_return_if_fail (format_state != NULL);
2703 format_state->bullet = gtk_toggle_action_get_active (action);
2704 modest_msg_edit_window_set_format_state (window, format_state);
2705 g_free (format_state);
2710 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2711 GtkRadioAction *selected,
2712 ModestMsgEditWindow *window)
2714 ModestMsgEditFormatState *format_state = NULL;
2715 GtkJustification value;
2717 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2719 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2722 value = gtk_radio_action_get_current_value (selected);
2724 format_state = modest_msg_edit_window_get_format_state (window);
2725 g_return_if_fail (format_state != NULL);
2727 format_state->justification = value;
2728 modest_msg_edit_window_set_format_state (window, format_state);
2729 g_free (format_state);
2733 modest_ui_actions_on_select_editor_color (GtkAction *action,
2734 ModestMsgEditWindow *window)
2736 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2737 g_return_if_fail (GTK_IS_ACTION (action));
2739 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2742 modest_msg_edit_window_select_color (window);
2746 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2747 ModestMsgEditWindow *window)
2749 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2750 g_return_if_fail (GTK_IS_ACTION (action));
2752 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2755 modest_msg_edit_window_select_background_color (window);
2759 modest_ui_actions_on_insert_image (GtkAction *action,
2760 ModestMsgEditWindow *window)
2762 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2763 g_return_if_fail (GTK_IS_ACTION (action));
2765 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2768 modest_msg_edit_window_insert_image (window);
2772 modest_ui_actions_on_attach_file (GtkAction *action,
2773 ModestMsgEditWindow *window)
2775 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2776 g_return_if_fail (GTK_IS_ACTION (action));
2778 modest_msg_edit_window_offer_attach_file (window);
2782 modest_ui_actions_on_remove_attachments (GtkAction *action,
2783 ModestMsgEditWindow *window)
2785 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2786 g_return_if_fail (GTK_IS_ACTION (action));
2788 modest_msg_edit_window_remove_attachments (window, NULL);
2792 do_create_folder_cb (ModestMailOperation *mail_op,
2793 TnyFolderStore *parent_folder,
2794 TnyFolder *new_folder,
2797 gchar *suggested_name = (gchar *) user_data;
2798 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2800 if (modest_mail_operation_get_error (mail_op)) {
2802 /* Show an error. If there was some problem writing to
2803 disk, show it, otherwise show the generic folder
2804 create error. We do it here and not in an error
2805 handler because the call to do_create_folder will
2806 stop the main loop in a gtk_dialog_run and then,
2807 the message won't be shown until that dialog is
2809 modest_ui_actions_disk_operations_error_handler (mail_op,
2810 _("mail_in_ui_folder_create_error"));
2812 /* Try again. Do *NOT* show any error because the mail
2813 operations system will do it for us because we
2814 created the mail_op with new_with_error_handler */
2815 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2817 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2818 * FIXME: any other? */
2819 GtkWidget *folder_view;
2821 if (MODEST_IS_MAIN_WINDOW(source_win))
2823 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2824 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2827 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2829 /* Select the newly created folder */
2830 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2832 g_object_unref (new_folder);
2834 /* Free. Note that the first time it'll be NULL so noop */
2835 g_free (suggested_name);
2836 g_object_unref (source_win);
2840 do_create_folder (GtkWindow *parent_window,
2841 TnyFolderStore *parent_folder,
2842 const gchar *suggested_name)
2845 gchar *folder_name = NULL;
2847 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2849 (gchar *) suggested_name,
2852 if (result == GTK_RESPONSE_ACCEPT) {
2853 ModestMailOperation *mail_op;
2855 mail_op = modest_mail_operation_new (NULL);
2856 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2858 modest_mail_operation_create_folder (mail_op,
2860 (const gchar *) folder_name,
2861 do_create_folder_cb,
2863 g_object_unref (mail_op);
2868 create_folder_performer (gboolean canceled,
2870 GtkWindow *parent_window,
2871 TnyAccount *account,
2874 TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2876 if (canceled || err) {
2880 /* Run the new folder dialog */
2881 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2884 g_object_unref (parent_folder);
2888 modest_ui_actions_create_folder(GtkWidget *parent_window,
2889 GtkWidget *folder_view)
2891 TnyFolderStore *parent_folder;
2893 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2895 if (parent_folder) {
2896 /* The parent folder will be freed in the callback */
2897 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
2900 create_folder_performer,
2906 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2908 GtkWidget *folder_view;
2910 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2912 folder_view = modest_main_window_get_child_widget (main_window,
2913 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2917 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2921 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2924 const GError *error = NULL;
2925 const gchar *message = NULL;
2927 /* Get error message */
2928 error = modest_mail_operation_get_error (mail_op);
2930 g_return_if_reached ();
2932 switch (error->code) {
2933 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2934 message = _CS("ckdg_ib_folder_already_exists");
2937 message = _("emev_ib_ui_imap_unable_to_rename");
2940 /* We don't set a parent for the dialog because the dialog
2941 will be destroyed so the banner won't appear */
2942 modest_platform_information_banner (NULL, NULL, message);
2946 TnyFolderStore *folder;
2951 on_rename_folder_cb (ModestMailOperation *mail_op,
2952 TnyFolder *new_folder,
2955 ModestFolderView *folder_view;
2957 folder_view = MODEST_FOLDER_VIEW (user_data);
2958 /* Note that if the rename fails new_folder will be NULL */
2960 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
2962 modest_folder_view_select_first_inbox_or_local (folder_view);
2967 on_rename_folder_performer (gboolean canceled,
2969 GtkWindow *parent_window,
2970 TnyAccount *account,
2973 ModestMailOperation *mail_op = NULL;
2974 GtkTreeSelection *sel = NULL;
2975 GtkWidget *folder_view = NULL;
2976 RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2978 if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2980 folder_view = modest_main_window_get_child_widget (
2981 MODEST_MAIN_WINDOW (parent_window),
2982 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2985 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2986 modest_ui_actions_rename_folder_error_handler,
2987 parent_window, NULL);
2989 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2992 /* Clear the headers view */
2993 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2994 gtk_tree_selection_unselect_all (sel);
2996 /* Actually rename the folder */
2997 modest_mail_operation_rename_folder (mail_op,
2998 TNY_FOLDER (data->folder),
2999 (const gchar *) (data->new_name),
3000 on_rename_folder_cb,
3004 g_object_unref (mail_op);
3005 g_free (data->new_name);
3010 modest_ui_actions_on_rename_folder (GtkAction *action,
3011 ModestMainWindow *main_window)
3013 TnyFolderStore *folder;
3014 GtkWidget *folder_view;
3015 GtkWidget *header_view;
3017 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3019 folder_view = modest_main_window_get_child_widget (main_window,
3020 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3024 header_view = modest_main_window_get_child_widget (main_window,
3025 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3030 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3035 if (TNY_IS_FOLDER (folder)) {
3038 const gchar *current_name;
3039 TnyFolderStore *parent;
3040 gboolean do_rename = TRUE;
3042 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3043 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3044 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
3045 parent, current_name,
3047 g_object_unref (parent);
3049 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3052 RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3053 rename_folder_data->folder = folder;
3054 rename_folder_data->new_name = folder_name;
3055 modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3056 folder, on_rename_folder_performer, rename_folder_data);
3059 g_object_unref (folder);
3063 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3066 GObject *win = modest_mail_operation_get_source (mail_op);
3068 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3069 _("mail_in_ui_folder_delete_error"));
3070 g_object_unref (win);
3074 TnyFolderStore *folder;
3075 gboolean move_to_trash;
3079 on_delete_folder_cb (gboolean canceled,
3081 GtkWindow *parent_window,
3082 TnyAccount *account,
3085 DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3086 GtkWidget *folder_view;
3087 ModestMailOperation *mail_op;
3088 GtkTreeSelection *sel;
3090 if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3091 g_object_unref (G_OBJECT (info->folder));
3096 folder_view = modest_main_window_get_child_widget (
3097 MODEST_MAIN_WINDOW (parent_window),
3098 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3100 /* Unselect the folder before deleting it to free the headers */
3101 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3102 gtk_tree_selection_unselect_all (sel);
3104 /* Create the mail operation */
3106 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3107 modest_ui_actions_delete_folder_error_handler,
3110 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3112 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3114 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3116 g_object_unref (G_OBJECT (mail_op));
3117 g_object_unref (G_OBJECT (info->folder));
3122 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3124 TnyFolderStore *folder;
3125 GtkWidget *folder_view;
3129 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3131 folder_view = modest_main_window_get_child_widget (main_window,
3132 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3136 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3138 /* Show an error if it's an account */
3139 if (!TNY_IS_FOLDER (folder)) {
3140 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3141 _("mail_in_ui_folder_delete_error"));
3142 g_object_unref (G_OBJECT (folder));
3147 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
3148 tny_folder_get_name (TNY_FOLDER (folder)));
3149 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3150 (const gchar *) message);
3153 if (response == GTK_RESPONSE_OK) {
3154 DeleteFolderInfo *info;
3155 info = g_new0(DeleteFolderInfo, 1);
3156 info->folder = folder;
3157 info->move_to_trash = move_to_trash;
3158 g_object_ref (G_OBJECT (info->folder));
3159 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3160 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window),
3162 TNY_FOLDER_STORE (account),
3163 on_delete_folder_cb, info);
3164 g_object_unref (account);
3166 g_object_unref (G_OBJECT (folder));
3170 modest_ui_actions_on_delete_folder (GtkAction *action,
3171 ModestMainWindow *main_window)
3173 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3175 delete_folder (main_window, FALSE);
3179 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3181 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3183 delete_folder (main_window, TRUE);
3188 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3189 const gchar* server_account_name,
3194 ModestMainWindow *main_window)
3196 g_return_if_fail(server_account_name);
3197 gboolean completed = FALSE;
3199 /* Initalize output parameters: */
3206 #ifdef MODEST_PLATFORM_MAEMO
3207 /* Maemo uses a different (awkward) button order,
3208 * It should probably just use gtk_alternative_dialog_button_order ().
3210 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3213 _("mcen_bd_dialog_ok"),
3214 GTK_RESPONSE_ACCEPT,
3215 _("mcen_bd_dialog_cancel"),
3216 GTK_RESPONSE_REJECT,
3219 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3223 GTK_RESPONSE_REJECT,
3225 GTK_RESPONSE_ACCEPT,
3227 #endif /* MODEST_PLATFORM_MAEMO */
3229 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3231 gchar *server_name = modest_account_mgr_get_server_account_hostname (
3232 modest_runtime_get_account_mgr(), server_account_name);
3233 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3234 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3240 /* This causes a warning because the logical ID has no %s in it,
3241 * though the translation does, but there is not much we can do about that: */
3242 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3243 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3246 g_free (server_name);
3250 gchar *initial_username = modest_account_mgr_get_server_account_username (
3251 modest_runtime_get_account_mgr(), server_account_name);
3253 GtkWidget *entry_username = gtk_entry_new ();
3254 if (initial_username)
3255 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3256 /* Dim this if a connection has ever succeeded with this username,
3257 * as per the UI spec: */
3258 const gboolean username_known =
3259 modest_account_mgr_get_server_account_username_has_succeeded(
3260 modest_runtime_get_account_mgr(), server_account_name);
3261 gtk_widget_set_sensitive (entry_username, !username_known);
3263 #ifdef MODEST_PLATFORM_MAEMO
3264 /* Auto-capitalization is the default, so let's turn it off: */
3265 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3267 /* Create a size group to be used by all captions.
3268 * Note that HildonCaption does not create a default size group if we do not specify one.
3269 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3270 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3272 GtkWidget *caption = hildon_caption_new (sizegroup,
3273 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3274 gtk_widget_show (entry_username);
3275 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3276 FALSE, FALSE, MODEST_MARGIN_HALF);
3277 gtk_widget_show (caption);
3279 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3281 #endif /* MODEST_PLATFORM_MAEMO */
3284 GtkWidget *entry_password = gtk_entry_new ();
3285 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3286 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3288 #ifdef MODEST_PLATFORM_MAEMO
3289 /* Auto-capitalization is the default, so let's turn it off: */
3290 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3291 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3293 caption = hildon_caption_new (sizegroup,
3294 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3295 gtk_widget_show (entry_password);
3296 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3297 FALSE, FALSE, MODEST_MARGIN_HALF);
3298 gtk_widget_show (caption);
3299 g_object_unref (sizegroup);
3301 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3303 #endif /* MODEST_PLATFORM_MAEMO */
3305 if (initial_username != NULL)
3306 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3308 /* This is not in the Maemo UI spec:
3309 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3310 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3314 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3316 while (!completed) {
3318 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3320 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3322 /* Note that an empty field becomes the "" string */
3323 if (*username && strlen (*username) > 0) {
3324 modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3325 server_account_name,
3329 const gboolean username_was_changed =
3330 (strcmp (*username, initial_username) != 0);
3331 if (username_was_changed) {
3332 g_warning ("%s: tinymail does not yet support changing the "
3333 "username in the get_password() callback.\n", __FUNCTION__);
3337 modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3338 _("mcen_ib_username_pw_incorrect"));
3344 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3346 /* We do not save the password in the configuration,
3347 * because this function is only called for passwords that should
3348 * not be remembered:
3349 modest_server_account_set_password (
3350 modest_runtime_get_account_mgr(), server_account_name,
3357 /* Set parent to NULL or the banner will disappear with its parent dialog */
3358 modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3369 /* This is not in the Maemo UI spec:
3370 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3376 gtk_widget_destroy (dialog);
3378 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3382 modest_ui_actions_on_cut (GtkAction *action,
3383 ModestWindow *window)
3385 GtkWidget *focused_widget;
3386 GtkClipboard *clipboard;
3388 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3389 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3390 if (GTK_IS_EDITABLE (focused_widget)) {
3391 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3392 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3393 gtk_clipboard_store (clipboard);
3394 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3395 GtkTextBuffer *buffer;
3397 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3398 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3399 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3400 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3401 gtk_clipboard_store (clipboard);
3403 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3404 TnyList *header_list = modest_header_view_get_selected_headers (
3405 MODEST_HEADER_VIEW (focused_widget));
3406 gboolean continue_download = FALSE;
3407 gint num_of_unc_msgs;
3409 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3411 if (num_of_unc_msgs) {
3412 TnyAccount *account = get_account_from_header_list (header_list);
3414 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3415 g_object_unref (account);
3419 if (num_of_unc_msgs == 0 || continue_download) {
3420 /* modest_platform_information_banner (
3421 NULL, NULL, _CS("mcen_ib_getting_items"));*/
3422 modest_header_view_cut_selection (
3423 MODEST_HEADER_VIEW (focused_widget));
3426 g_object_unref (header_list);
3427 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3428 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3433 modest_ui_actions_on_copy (GtkAction *action,
3434 ModestWindow *window)
3436 GtkClipboard *clipboard;
3437 GtkWidget *focused_widget;
3438 gboolean copied = TRUE;
3440 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3441 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3443 if (GTK_IS_LABEL (focused_widget)) {
3445 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3446 gtk_clipboard_set_text (clipboard, selection, -1);
3448 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3449 gtk_clipboard_store (clipboard);
3450 } else if (GTK_IS_EDITABLE (focused_widget)) {
3451 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3452 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3453 gtk_clipboard_store (clipboard);
3454 } else if (GTK_IS_HTML (focused_widget)) {
3455 gtk_html_copy (GTK_HTML (focused_widget));
3456 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3457 gtk_clipboard_store (clipboard);
3458 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3459 GtkTextBuffer *buffer;
3460 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3461 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3462 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3463 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3464 gtk_clipboard_store (clipboard);
3466 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3467 TnyList *header_list = modest_header_view_get_selected_headers (
3468 MODEST_HEADER_VIEW (focused_widget));
3469 gboolean continue_download = FALSE;
3470 gint num_of_unc_msgs;
3472 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3474 if (num_of_unc_msgs) {
3475 TnyAccount *account = get_account_from_header_list (header_list);
3477 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3478 g_object_unref (account);
3482 if (num_of_unc_msgs == 0 || continue_download) {
3483 modest_platform_information_banner (
3484 NULL, NULL, _CS("mcen_ib_getting_items"));
3485 modest_header_view_copy_selection (
3486 MODEST_HEADER_VIEW (focused_widget));
3490 g_object_unref (header_list);
3492 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3493 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3496 /* Show information banner if there was a copy to clipboard */
3498 modest_platform_information_banner (
3499 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3503 modest_ui_actions_on_undo (GtkAction *action,
3504 ModestWindow *window)
3506 ModestEmailClipboard *clipboard = NULL;
3508 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3509 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3510 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3511 /* Clear clipboard source */
3512 clipboard = modest_runtime_get_email_clipboard ();
3513 modest_email_clipboard_clear (clipboard);
3516 g_return_if_reached ();
3521 modest_ui_actions_on_redo (GtkAction *action,
3522 ModestWindow *window)
3524 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3525 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3528 g_return_if_reached ();
3534 destroy_information_note (ModestMailOperation *mail_op,
3537 /* destroy information note */
3538 gtk_widget_destroy (GTK_WIDGET(user_data));
3542 destroy_folder_information_note (ModestMailOperation *mail_op,
3543 TnyFolder *new_folder,
3546 /* destroy information note */
3547 gtk_widget_destroy (GTK_WIDGET(user_data));
3552 paste_as_attachment_free (gpointer data)
3554 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3556 gtk_widget_destroy (helper->banner);
3557 g_object_unref (helper->banner);
3562 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3567 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3568 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3573 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3578 modest_ui_actions_on_paste (GtkAction *action,
3579 ModestWindow *window)
3581 GtkWidget *focused_widget = NULL;
3582 GtkWidget *inf_note = NULL;
3583 ModestMailOperation *mail_op = NULL;
3585 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3586 if (GTK_IS_EDITABLE (focused_widget)) {
3587 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3588 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3589 ModestEmailClipboard *e_clipboard = NULL;
3590 e_clipboard = modest_runtime_get_email_clipboard ();
3591 if (modest_email_clipboard_cleared (e_clipboard)) {
3592 GtkTextBuffer *buffer;
3593 GtkClipboard *clipboard;
3595 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3596 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3597 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3598 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3599 ModestMailOperation *mail_op;
3600 TnyFolder *src_folder;
3603 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3604 helper->window = MODEST_MSG_EDIT_WINDOW (window);
3605 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3606 _CS("ckct_nw_pasting"));
3607 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3608 mail_op = modest_mail_operation_new (G_OBJECT (window));
3609 if (helper->banner != NULL) {
3610 g_object_ref (G_OBJECT (helper->banner));
3611 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3612 gtk_widget_show (GTK_WIDGET (helper->banner));
3616 modest_mail_operation_get_msgs_full (mail_op,
3618 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3620 paste_as_attachment_free);
3623 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3624 ModestEmailClipboard *clipboard = NULL;
3625 TnyFolder *src_folder = NULL;
3626 TnyFolderStore *folder_store = NULL;
3627 TnyList *data = NULL;
3628 gboolean delete = FALSE;
3630 /* Check clipboard source */
3631 clipboard = modest_runtime_get_email_clipboard ();
3632 if (modest_email_clipboard_cleared (clipboard))
3635 /* Get elements to paste */
3636 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3638 /* Create a new mail operation */
3639 mail_op = modest_mail_operation_new (G_OBJECT(window));
3641 /* Get destination folder */
3642 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3644 /* transfer messages */
3648 /* Ask for user confirmation */
3650 modest_ui_actions_msgs_move_to_confirmation (window,
3651 TNY_FOLDER (folder_store),
3655 if (response == GTK_RESPONSE_OK) {
3656 /* Launch notification */
3657 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3658 _CS("ckct_nw_pasting"));
3659 if (inf_note != NULL) {
3660 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3661 gtk_widget_show (GTK_WIDGET(inf_note));
3664 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3665 modest_mail_operation_xfer_msgs (mail_op,
3667 TNY_FOLDER (folder_store),
3669 destroy_information_note,
3672 g_object_unref (mail_op);
3675 } else if (src_folder != NULL) {
3676 /* Launch notification */
3677 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3678 _CS("ckct_nw_pasting"));
3679 if (inf_note != NULL) {
3680 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3681 gtk_widget_show (GTK_WIDGET(inf_note));
3684 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3685 modest_mail_operation_xfer_folder (mail_op,
3689 destroy_folder_information_note,
3695 g_object_unref (data);
3696 if (src_folder != NULL)
3697 g_object_unref (src_folder);
3698 if (folder_store != NULL)
3699 g_object_unref (folder_store);
3705 modest_ui_actions_on_select_all (GtkAction *action,
3706 ModestWindow *window)
3708 GtkWidget *focused_widget;
3710 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3711 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3712 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3713 } else if (GTK_IS_LABEL (focused_widget)) {
3714 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3715 } else if (GTK_IS_EDITABLE (focused_widget)) {
3716 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3717 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3718 GtkTextBuffer *buffer;
3719 GtkTextIter start, end;
3721 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3722 gtk_text_buffer_get_start_iter (buffer, &start);
3723 gtk_text_buffer_get_end_iter (buffer, &end);
3724 gtk_text_buffer_select_range (buffer, &start, &end);
3725 } else if (GTK_IS_HTML (focused_widget)) {
3726 gtk_html_select_all (GTK_HTML (focused_widget));
3727 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3728 GtkWidget *header_view = focused_widget;
3729 GtkTreeSelection *selection = NULL;
3731 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3732 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3733 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3736 /* Disable window dimming management */
3737 modest_window_disable_dimming (MODEST_WINDOW(window));
3739 /* Select all messages */
3740 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3741 gtk_tree_selection_select_all (selection);
3743 /* Set focuse on header view */
3744 gtk_widget_grab_focus (header_view);
3747 /* Enable window dimming management */
3748 modest_window_enable_dimming (MODEST_WINDOW(window));
3749 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3755 modest_ui_actions_on_mark_as_read (GtkAction *action,
3756 ModestWindow *window)
3758 g_return_if_fail (MODEST_IS_WINDOW(window));
3760 /* Mark each header as read */
3761 do_headers_action (window, headers_action_mark_as_read, NULL);
3765 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3766 ModestWindow *window)
3768 g_return_if_fail (MODEST_IS_WINDOW(window));
3770 /* Mark each header as read */
3771 do_headers_action (window, headers_action_mark_as_unread, NULL);
3775 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3776 GtkRadioAction *selected,
3777 ModestWindow *window)
3781 value = gtk_radio_action_get_current_value (selected);
3782 if (MODEST_IS_WINDOW (window)) {
3783 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3788 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3789 GtkRadioAction *selected,
3790 ModestWindow *window)
3792 TnyHeaderFlags flags;
3793 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3795 flags = gtk_radio_action_get_current_value (selected);
3796 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3800 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3801 GtkRadioAction *selected,
3802 ModestWindow *window)
3806 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3808 file_format = gtk_radio_action_get_current_value (selected);
3809 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3814 modest_ui_actions_on_zoom_plus (GtkAction *action,
3815 ModestWindow *window)
3817 g_return_if_fail (MODEST_IS_WINDOW (window));
3819 modest_window_zoom_plus (MODEST_WINDOW (window));
3823 modest_ui_actions_on_zoom_minus (GtkAction *action,
3824 ModestWindow *window)
3826 g_return_if_fail (MODEST_IS_WINDOW (window));
3828 modest_window_zoom_minus (MODEST_WINDOW (window));
3832 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
3833 ModestWindow *window)
3835 ModestWindowMgr *mgr;
3836 gboolean fullscreen, active;
3837 g_return_if_fail (MODEST_IS_WINDOW (window));
3839 mgr = modest_runtime_get_window_mgr ();
3841 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3842 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3844 if (active != fullscreen) {
3845 modest_window_mgr_set_fullscreen_mode (mgr, active);
3846 gtk_window_present (GTK_WINDOW (window));
3851 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3852 ModestWindow *window)
3854 ModestWindowMgr *mgr;
3855 gboolean fullscreen;
3857 g_return_if_fail (MODEST_IS_WINDOW (window));
3859 mgr = modest_runtime_get_window_mgr ();
3860 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3861 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3863 gtk_window_present (GTK_WINDOW (window));
3867 * Used by modest_ui_actions_on_details to call do_headers_action
3870 headers_action_show_details (TnyHeader *header,
3871 ModestWindow *window,
3878 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3881 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3882 gtk_widget_show_all (dialog);
3883 gtk_dialog_run (GTK_DIALOG (dialog));
3885 gtk_widget_destroy (dialog);
3889 * Show the folder details in a ModestDetailsDialog widget
3892 show_folder_details (TnyFolder *folder,
3898 dialog = modest_details_dialog_new_with_folder (window, folder);
3901 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3902 gtk_widget_show_all (dialog);
3903 gtk_dialog_run (GTK_DIALOG (dialog));
3905 gtk_widget_destroy (dialog);
3909 * Show the header details in a ModestDetailsDialog widget
3912 modest_ui_actions_on_details (GtkAction *action,
3915 TnyList * headers_list;
3919 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3922 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3925 g_object_unref (msg);
3927 headers_list = get_selected_headers (win);
3931 iter = tny_list_create_iterator (headers_list);
3933 header = TNY_HEADER (tny_iterator_get_current (iter));
3935 headers_action_show_details (header, win, NULL);
3936 g_object_unref (header);
3939 g_object_unref (iter);
3940 g_object_unref (headers_list);
3942 } else if (MODEST_IS_MAIN_WINDOW (win)) {
3943 GtkWidget *folder_view, *header_view;
3945 /* Check which widget has the focus */
3946 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3947 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3948 if (gtk_widget_is_focus (folder_view)) {
3949 TnyFolderStore *folder_store
3950 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3951 if (!folder_store) {
3952 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3955 /* Show only when it's a folder */
3956 /* This function should not be called for account items,
3957 * because we dim the menu item for them. */
3958 if (TNY_IS_FOLDER (folder_store)) {
3959 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3962 g_object_unref (folder_store);
3965 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3966 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3967 /* Show details of each header */
3968 do_headers_action (win, headers_action_show_details, header_view);
3974 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3975 ModestMsgEditWindow *window)
3977 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3979 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3983 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3984 ModestMsgEditWindow *window)
3986 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3988 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3992 modest_ui_actions_toggle_folders_view (GtkAction *action,
3993 ModestMainWindow *main_window)
3995 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3997 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3998 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4000 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4004 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4005 ModestWindow *window)
4007 gboolean active, fullscreen = FALSE;
4008 ModestWindowMgr *mgr;
4010 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4012 /* Check if we want to toggle the toolbar vuew in fullscreen
4014 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4015 "ViewShowToolbarFullScreen")) {
4019 /* Toggle toolbar */
4020 mgr = modest_runtime_get_window_mgr ();
4021 modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4025 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4026 ModestMsgEditWindow *window)
4028 modest_msg_edit_window_select_font (window);
4033 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4034 const gchar *display_name,
4037 /* don't update the display name if it was already set;
4038 * updating the display name apparently is expensive */
4039 const gchar* old_name = gtk_window_get_title (window);
4041 if (display_name == NULL)
4044 if (old_name && display_name && strcmp (old_name, display_name) == 0)
4045 return; /* don't do anything */
4047 /* This is usually used to change the title of the main window, which
4048 * is the one that holds the folder view. Note that this change can
4049 * happen even when the widget doesn't have the focus. */
4050 gtk_window_set_title (window, display_name);
4055 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4057 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4058 modest_msg_edit_window_select_contacts (window);
4062 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4064 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4065 modest_msg_edit_window_check_names (window, FALSE);
4069 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4071 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4072 GTK_WIDGET (user_data));
4076 * This function is used to track changes in the selection of the
4077 * folder view that is inside the "move to" dialog to enable/disable
4078 * the OK button because we do not want the user to select a disallowed
4079 * destination for a folder.
4080 * The user also not desired to be able to use NEW button on items where
4081 * folder creation is not possibel.
4084 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4085 TnyFolderStore *folder_store,
4089 GtkWidget *dialog = NULL;
4090 GtkWidget *ok_button = NULL, *new_button = NULL;
4091 GList *children = NULL;
4092 gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4093 gboolean moving_folder = FALSE;
4094 gboolean is_local_account = TRUE;
4095 GtkWidget *folder_view = NULL;
4096 ModestTnyFolderRules rules;
4098 g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4103 /* Get the OK button */
4104 dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4108 children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4109 ok_button = GTK_WIDGET (children->next->next->data);
4110 new_button = GTK_WIDGET (children->next->data);
4111 g_list_free (children);
4113 /* check if folder_store is an remote account */
4114 if (TNY_IS_ACCOUNT (folder_store)) {
4115 TnyAccount *local_account = NULL;
4116 TnyAccount *mmc_account = NULL;
4117 ModestTnyAccountStore *account_store = NULL;
4119 account_store = modest_runtime_get_account_store ();
4120 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4121 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4123 if ((gpointer) local_account != (gpointer) folder_store &&
4124 (gpointer) mmc_account != (gpointer) folder_store) {
4125 const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4126 ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4127 if (proto_name != NULL) {
4128 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4130 is_local_account = FALSE;
4131 /* New button should be dimmed on remote
4133 new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4135 g_object_unref (local_account);
4136 g_object_unref (mmc_account);
4139 /* Check the target folder rules */
4140 if (TNY_IS_FOLDER (folder_store)) {
4141 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4142 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4143 ok_sensitive = FALSE;
4144 new_sensitive = FALSE;
4149 /* Check if we're moving a folder */
4150 if (MODEST_IS_MAIN_WINDOW (user_data)) {
4151 /* Get the widgets */
4152 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4153 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4154 if (gtk_widget_is_focus (folder_view))
4155 moving_folder = TRUE;
4158 if (moving_folder) {
4159 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4161 /* Get the folder to move */
4162 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4164 /* Check that we're not moving to the same folder */
4165 if (TNY_IS_FOLDER (moved_folder)) {
4166 parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4167 if (parent == folder_store)
4168 ok_sensitive = FALSE;
4169 g_object_unref (parent);
4172 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4173 /* Do not allow to move to an account unless it's the
4174 local folders account */
4175 if (!is_local_account)
4176 ok_sensitive = FALSE;
4179 if (ok_sensitive && (moved_folder == folder_store)) {
4180 /* Do not allow to move to itself */
4181 ok_sensitive = FALSE;
4183 g_object_unref (moved_folder);
4185 TnyFolder *src_folder = NULL;
4187 /* Moving a message */
4188 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4190 TnyHeader *header = NULL;
4191 header = modest_msg_view_window_get_header
4192 (MODEST_MSG_VIEW_WINDOW (user_data));
4193 if (!TNY_IS_HEADER(header))
4194 g_warning ("%s: could not get source header", __FUNCTION__);
4196 src_folder = tny_header_get_folder (header);
4199 g_object_unref (header);
4202 TNY_FOLDER (modest_folder_view_get_selected
4203 (MODEST_FOLDER_VIEW (folder_view)));
4206 if (TNY_IS_FOLDER(src_folder)) {
4207 /* Do not allow to move the msg to the same folder */
4208 /* Do not allow to move the msg to an account */
4209 if ((gpointer) src_folder == (gpointer) folder_store ||
4210 TNY_IS_ACCOUNT (folder_store))
4211 ok_sensitive = FALSE;
4212 g_object_unref (src_folder);
4214 g_warning ("%s: could not get source folder", __FUNCTION__);
4218 /* Set sensitivity of the OK button */
4219 gtk_widget_set_sensitive (ok_button, ok_sensitive);
4220 /* Set sensitivity of the NEW button */
4221 gtk_widget_set_sensitive (new_button, new_sensitive);
4225 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4228 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4230 return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4231 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4235 create_move_to_dialog (GtkWindow *win,
4236 GtkWidget *folder_view,
4237 GtkWidget **tree_view)
4239 GtkWidget *dialog, *scroll;
4240 GtkWidget *new_button;
4242 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4244 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4247 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4248 /* We do this manually so GTK+ does not associate a response ID for
4250 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4251 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4252 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4254 /* Create scrolled window */
4255 scroll = gtk_scrolled_window_new (NULL, NULL);
4256 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
4257 GTK_POLICY_AUTOMATIC,
4258 GTK_POLICY_AUTOMATIC);
4260 /* Create folder view */
4261 *tree_view = modest_platform_create_folder_view (NULL);
4263 /* Track changes in the selection to
4264 * disable the OK button whenever "Move to" is not possible
4265 * disbale NEW button whenever New is not possible */
4266 g_signal_connect (*tree_view,
4267 "folder_selection_changed",
4268 G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4271 /* Listen to clicks on New button */
4272 g_signal_connect (G_OBJECT (new_button),
4274 G_CALLBACK(create_move_to_dialog_on_new_folder),
4277 /* It could happen that we're trying to move a message from a
4278 window (msg window for example) after the main window was
4279 closed, so we can not just get the model of the folder
4281 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4282 const gchar *visible_id = NULL;
4284 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4285 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4286 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4287 MODEST_FOLDER_VIEW(*tree_view));
4290 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4292 /* Show the same account than the one that is shown in the main window */
4293 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
4296 const gchar *active_account_name = NULL;
4297 ModestAccountMgr *mgr = NULL;
4298 ModestAccountSettings *settings = NULL;
4299 ModestServerAccountSettings *store_settings = NULL;
4301 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4302 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4303 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
4304 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4306 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4307 mgr = modest_runtime_get_account_mgr ();
4308 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4311 const gchar *store_account_name;
4312 store_settings = modest_account_settings_get_store_settings (settings);
4313 store_account_name = modest_server_account_settings_get_account_name (store_settings);
4315 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4316 store_account_name);
4317 g_object_unref (store_settings);
4318 g_object_unref (settings);
4322 /* we keep a pointer to the embedded folder view, so we can retrieve it with
4323 * get_folder_view_from_move_to_dialog
4324 * (see above) later (needed for focus handling)
4326 g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4329 /* Hide special folders */
4330 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4332 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4334 /* Add scroll to dialog */
4335 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
4336 scroll, TRUE, TRUE, 0);
4338 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4339 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4345 * Returns TRUE if at least one of the headers of the list belongs to
4346 * a message that has been fully retrieved.
4348 #if 0 /* no longer in use. delete in 2007.10 */
4350 has_retrieved_msgs (TnyList *list)
4353 gboolean found = FALSE;
4355 iter = tny_list_create_iterator (list);
4356 while (!tny_iterator_is_done (iter) && !found) {
4358 TnyHeaderFlags flags = 0;
4360 header = TNY_HEADER (tny_iterator_get_current (iter));
4362 flags = tny_header_get_flags (header);
4363 if (flags & TNY_HEADER_FLAG_CACHED)
4364 /* if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4367 g_object_unref (header);
4371 tny_iterator_next (iter);
4373 g_object_unref (iter);
4381 * Shows a confirmation dialog to the user when we're moving messages
4382 * from a remote server to the local storage. Returns the dialog
4383 * response. If it's other kind of movement then it always returns
4386 * This one is used by the next functions:
4387 * modest_ui_actions_on_paste - commented out
4388 * drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4391 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4392 TnyFolder *dest_folder,
4396 gint response = GTK_RESPONSE_OK;
4397 TnyAccount *account = NULL;
4398 TnyFolder *src_folder = NULL;
4399 TnyIterator *iter = NULL;
4400 TnyHeader *header = NULL;
4402 /* return with OK if the destination is a remote folder */
4403 if (modest_tny_folder_is_remote_folder (dest_folder))
4404 return GTK_RESPONSE_OK;
4406 /* Get source folder */
4407 iter = tny_list_create_iterator (headers);
4408 header = TNY_HEADER (tny_iterator_get_current (iter));
4410 src_folder = tny_header_get_folder (header);
4411 g_object_unref (header);
4413 g_object_unref (iter);
4415 /* if no src_folder, message may be an attahcment */
4416 if (src_folder == NULL)
4417 return GTK_RESPONSE_CANCEL;
4419 /* If the source is a local or MMC folder */
4420 if (!modest_tny_folder_is_remote_folder (src_folder)) {
4421 g_object_unref (src_folder);
4422 return GTK_RESPONSE_OK;
4425 /* Get the account */
4426 account = tny_folder_get_account (src_folder);
4428 /* now if offline we ask the user */
4429 if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4430 response = GTK_RESPONSE_OK;
4432 response = GTK_RESPONSE_CANCEL;
4435 g_object_unref (src_folder);
4436 g_object_unref (account);
4442 move_to_cb (ModestMailOperation *mail_op,
4445 MoveToHelper *helper = (MoveToHelper *) user_data;
4447 /* Note that the operation could have failed, in that case do
4449 if (modest_mail_operation_get_status (mail_op) ==
4450 MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4452 GObject *object = modest_mail_operation_get_source (mail_op);
4453 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4454 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4456 if (!modest_msg_view_window_select_next_message (self) &&
4457 !modest_msg_view_window_select_previous_message (self)) {
4458 /* No more messages to view, so close this window */
4459 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4461 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4462 GtkWidget *header_view;
4464 GtkTreeSelection *sel;
4466 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4467 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4468 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4469 path = gtk_tree_row_reference_get_path (helper->reference);
4470 gtk_tree_selection_select_path (sel, path);
4471 gtk_tree_path_free (path);
4473 g_object_unref (object);
4476 /* Close the "Pasting" information banner */
4477 gtk_widget_destroy (GTK_WIDGET(helper->banner));
4478 if (helper->reference != NULL)
4479 gtk_tree_row_reference_free (helper->reference);
4484 folder_move_to_cb (ModestMailOperation *mail_op,
4485 TnyFolder *new_folder,
4488 GtkWidget *folder_view;
4491 object = modest_mail_operation_get_source (mail_op);
4492 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4493 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4494 g_object_ref (folder_view);
4495 g_object_unref (object);
4496 move_to_cb (mail_op, user_data);
4497 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4498 g_object_unref (folder_view);
4502 msgs_move_to_cb (ModestMailOperation *mail_op,
4505 move_to_cb (mail_op, user_data);
4509 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4512 ModestWindow *main_window = NULL;
4513 GObject *win = NULL;
4515 /* Disable next automatic folder selection */
4516 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4517 FALSE); /* don't create */
4519 GtkWidget *folder_view = NULL;
4521 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4522 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4523 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4525 if (user_data && TNY_IS_FOLDER (user_data)) {
4526 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
4527 TNY_FOLDER (user_data), FALSE);
4531 /* Show notification dialog */
4532 win = modest_mail_operation_get_source (mail_op);
4533 modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4535 g_object_unref (win);
4539 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op,
4542 GObject *win = modest_mail_operation_get_source (mail_op);
4543 const GError *error = modest_mail_operation_get_error (mail_op);
4545 g_return_if_fail (error != NULL);
4546 if (error->message != NULL)
4547 g_printerr ("modest: %s\n", error->message);
4549 g_printerr ("modest: unkonw error on send&receive operation");
4551 /* Show error message */
4552 /* if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4553 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4554 /* _CS("sfil_ib_unable_to_receive")); */
4556 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4557 /* _CS("sfil_ib_unable_to_send")); */
4558 g_object_unref (win);
4562 open_msg_for_purge_cb (ModestMailOperation *mail_op,
4571 gint pending_purges = 0;
4572 gboolean some_purged = FALSE;
4573 ModestWindow *win = MODEST_WINDOW (user_data);
4574 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4576 /* If there was any error */
4577 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4578 modest_window_mgr_unregister_header (mgr, header);
4582 /* Once the message has been retrieved for purging, we check if
4583 * it's all ok for purging */
4585 parts = tny_simple_list_new ();
4586 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4587 iter = tny_list_create_iterator (parts);
4589 while (!tny_iterator_is_done (iter)) {
4591 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4592 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4593 if (tny_mime_part_is_purged (part))
4600 g_object_unref (part);
4602 tny_iterator_next (iter);
4604 g_object_unref (iter);
4607 if (pending_purges>0) {
4609 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4611 if (response == GTK_RESPONSE_OK) {
4612 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4613 iter = tny_list_create_iterator (parts);
4614 while (!tny_iterator_is_done (iter)) {
4617 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4618 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4619 tny_mime_part_set_purged (part);
4622 g_object_unref (part);
4624 tny_iterator_next (iter);
4626 g_object_unref (iter);
4628 tny_msg_rewrite_cache (msg);
4631 /* This string no longer exists, refer to NB#75415 for more info */
4632 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4635 modest_window_mgr_unregister_header (mgr, header);
4637 g_object_unref (parts);
4641 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4642 ModestMainWindow *win)
4644 GtkWidget *header_view;
4645 TnyList *header_list;
4647 TnyHeaderFlags flags;
4648 ModestWindow *msg_view_window = NULL;
4651 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4653 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4654 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4656 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4658 g_warning ("%s: no header selected", __FUNCTION__);
4662 if (tny_list_get_length (header_list) == 1) {
4663 TnyIterator *iter = tny_list_create_iterator (header_list);
4664 header = TNY_HEADER (tny_iterator_get_current (iter));
4665 g_object_unref (iter);
4669 if (!header || !TNY_IS_HEADER(header)) {
4670 g_warning ("%s: header is not valid", __FUNCTION__);
4674 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4675 header, &msg_view_window);
4676 flags = tny_header_get_flags (header);
4677 if (!(flags & TNY_HEADER_FLAG_CACHED))
4680 if (msg_view_window != NULL)
4681 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4683 /* do nothing; uid was registered before, so window is probably on it's way */
4684 g_warning ("debug: header %p has already been registered", header);
4687 ModestMailOperation *mail_op = NULL;
4688 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4689 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4690 modest_ui_actions_disk_operations_error_handler,
4692 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4693 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4695 g_object_unref (mail_op);
4698 g_object_unref (header);
4700 g_object_unref (header_list);
4704 * Checks if we need a connection to do the transfer and if the user
4705 * wants to connect to complete it
4708 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4709 TnyFolderStore *src_folder,
4711 TnyFolder *dst_folder,
4712 gboolean delete_originals,
4713 gboolean *need_connection,
4716 TnyAccount *src_account;
4717 gint uncached_msgs = 0;
4719 uncached_msgs = header_list_count_uncached_msgs (headers);
4721 /* We don't need any further check if
4723 * 1- the source folder is local OR
4724 * 2- the device is already online
4726 if (!modest_tny_folder_store_is_remote (src_folder) ||
4727 tny_device_is_online (modest_runtime_get_device())) {
4728 *need_connection = FALSE;
4733 /* We must ask for a connection when
4735 * - the message(s) is not already cached OR
4736 * - the message(s) is cached but the leave_on_server setting
4737 * is FALSE (because we need to sync the source folder to
4738 * delete the message from the server (for IMAP we could do it
4739 * offline, it'll take place the next time we get a
4742 src_account = get_account_from_folder_store (src_folder);
4743 if (uncached_msgs > 0) {
4747 *need_connection = TRUE;
4748 num_headers = tny_list_get_length (headers);
4749 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4751 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4752 GTK_RESPONSE_CANCEL) {
4758 /* The transfer is possible and the user wants to */
4761 if (remote_folder_is_pop (src_folder) && delete_originals) {
4762 const gchar *account_name;
4763 gboolean leave_on_server;
4765 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4766 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4769 if (leave_on_server == TRUE) {
4770 *need_connection = FALSE;
4772 *need_connection = TRUE;
4775 *need_connection = FALSE;
4780 g_object_unref (src_account);
4785 * Utility function that transfer messages from both the main window
4786 * and the msg view window when using the "Move to" dialog
4789 xfer_messages_performer (gboolean canceled,
4791 GtkWindow *parent_window,
4792 TnyAccount *account,
4795 TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4796 ModestWindow *win = MODEST_WINDOW (parent_window);
4797 TnyList *headers = NULL;
4798 TnyAccount *dst_account = NULL;
4799 const gchar *proto_str = NULL;
4800 gboolean dst_is_pop = FALSE;
4802 if (canceled || err) {
4803 /* Show the proper error message */
4804 modest_ui_actions_on_account_connection_error (parent_window, account);
4805 g_object_unref (dst_folder);
4809 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4810 proto_str = tny_account_get_proto (dst_account);
4812 /* tinymail will return NULL for local folders it seems */
4813 dst_is_pop = proto_str &&
4814 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
4815 MODEST_PROTOCOL_STORE_POP);
4817 g_object_unref (dst_account);
4819 /* Get selected headers */
4820 headers = get_selected_headers (MODEST_WINDOW (win));
4822 g_warning ("%s: no headers selected", __FUNCTION__);
4828 modest_platform_information_banner (GTK_WIDGET (win),
4830 ngettext("mail_in_ui_folder_move_target_error",
4831 "mail_in_ui_folder_move_targets_error",
4832 tny_list_get_length (headers)));
4833 g_object_unref (headers);
4837 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4838 helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4839 _CS("ckct_nw_pasting"));
4840 if (helper->banner != NULL) {
4841 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4842 gtk_widget_show (GTK_WIDGET(helper->banner));
4845 if (MODEST_IS_MAIN_WINDOW (win)) {
4846 GtkWidget *header_view =
4847 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4848 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4849 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4852 ModestMailOperation *mail_op =
4853 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4854 modest_ui_actions_move_folder_error_handler,
4856 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4859 modest_mail_operation_xfer_msgs (mail_op,
4861 TNY_FOLDER (dst_folder),
4866 g_object_unref (G_OBJECT (mail_op));
4867 g_object_unref (headers);
4868 g_object_unref (dst_folder);
4872 TnyFolder *src_folder;
4873 TnyFolderStore *dst_folder;
4874 gboolean delete_original;
4875 GtkWidget *folder_view;
4879 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
4880 TnyAccount *account, gpointer user_data)
4882 MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4883 GtkTreeSelection *sel;
4884 ModestMailOperation *mail_op = NULL;
4886 if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4887 g_object_unref (G_OBJECT (info->src_folder));
4888 g_object_unref (G_OBJECT (info->dst_folder));
4893 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4894 helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4895 _CS("ckct_nw_pasting"));
4896 if (helper->banner != NULL) {
4897 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4898 gtk_widget_show (GTK_WIDGET(helper->banner));
4900 /* Clean folder on header view before moving it */
4901 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4902 gtk_tree_selection_unselect_all (sel);
4904 /* Let gtk events run. We need that the folder
4905 view frees its reference to the source
4906 folder *before* issuing the mail operation
4907 so we need the signal handler of selection
4908 changed to happen before the mail
4910 while (gtk_events_pending ())
4911 gtk_main_iteration (); */
4914 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4915 modest_ui_actions_move_folder_error_handler,
4916 info->src_folder, NULL);
4917 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4920 /* Select *after* the changes */
4921 /* TODO: this function hangs UI after transfer */
4922 /* modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4923 /* TNY_FOLDER (src_folder), TRUE); */
4925 modest_mail_operation_xfer_folder (mail_op,
4926 TNY_FOLDER (info->src_folder),
4928 info->delete_original,
4932 if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4933 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4934 TNY_FOLDER (info->dst_folder), TRUE);
4937 /* Unref mail operation */
4938 g_object_unref (G_OBJECT (mail_op));
4939 g_object_unref (G_OBJECT (info->src_folder));
4940 g_object_unref (G_OBJECT (info->dst_folder));
4945 get_account_from_folder_store (TnyFolderStore *folder_store)
4947 if (TNY_IS_ACCOUNT (folder_store))
4948 return g_object_ref (folder_store);
4950 return tny_folder_get_account (TNY_FOLDER (folder_store));
4954 * UI handler for the "Move to" action when invoked from the
4958 modest_ui_actions_on_main_window_move_to (GtkAction *action,
4959 GtkWidget *folder_view,
4960 TnyFolderStore *dst_folder,
4961 ModestMainWindow *win)
4963 ModestHeaderView *header_view = NULL;
4964 TnyFolderStore *src_folder = NULL;
4966 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4968 /* Get the source folder */
4969 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4971 /* Get header view */
4972 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4974 /* Get folder or messages to transfer */
4975 if (gtk_widget_is_focus (folder_view)) {
4976 gboolean do_xfer = TRUE;
4978 /* Allow only to transfer folders to the local root folder */
4979 if (TNY_IS_ACCOUNT (dst_folder) &&
4980 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4981 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4983 } else if (!TNY_IS_FOLDER (src_folder)) {
4984 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4989 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4990 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4992 info->src_folder = g_object_ref (src_folder);
4993 info->dst_folder = g_object_ref (dst_folder);
4994 info->delete_original = TRUE;
4995 info->folder_view = folder_view;
4997 connect_info->callback = on_move_folder_cb;
4998 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4999 connect_info->data = info;
5001 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5002 TNY_FOLDER_STORE (src_folder),
5005 } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5008 headers = modest_header_view_get_selected_headers(header_view);
5010 /* Transfer the messages */
5011 transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5012 headers, TNY_FOLDER (dst_folder));
5014 g_object_unref (headers);
5018 g_object_unref (src_folder);
5023 transfer_messages_helper (GtkWindow *win,
5024 TnyFolder *src_folder,
5026 TnyFolder *dst_folder)
5028 gboolean need_connection = TRUE;
5029 gboolean do_xfer = TRUE;
5031 modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5032 headers, TNY_FOLDER (dst_folder),
5033 TRUE, &need_connection,
5036 /* If we don't want to transfer just return */
5040 if (need_connection) {
5041 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5042 connect_info->callback = xfer_messages_performer;
5043 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5044 connect_info->data = g_object_ref (dst_folder);
5046 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5047 TNY_FOLDER_STORE (src_folder),
5050 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5051 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5053 g_object_ref (dst_folder));
5054 g_object_unref (src_account);
5059 * UI handler for the "Move to" action when invoked from the
5060 * ModestMsgViewWindow
5063 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
5064 TnyFolderStore *dst_folder,
5065 ModestMsgViewWindow *win)
5067 TnyList *headers = NULL;
5068 TnyHeader *header = NULL;
5069 TnyFolder *src_folder = NULL;
5071 g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5073 /* Create header list */
5074 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5075 src_folder = TNY_FOLDER (tny_header_get_folder(header));
5076 headers = tny_simple_list_new ();
5077 tny_list_append (headers, G_OBJECT (header));
5079 /* Transfer the messages */
5080 transfer_messages_helper (GTK_WINDOW (win), src_folder, headers,
5081 TNY_FOLDER (dst_folder));
5084 g_object_unref (header);
5085 g_object_unref (headers);
5089 modest_ui_actions_on_move_to (GtkAction *action,
5092 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5094 TnyFolderStore *dst_folder = NULL;
5095 ModestMainWindow *main_window;
5097 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5098 MODEST_IS_MSG_VIEW_WINDOW (win));
5100 /* Get the main window if exists */
5101 if (MODEST_IS_MAIN_WINDOW (win))
5102 main_window = MODEST_MAIN_WINDOW (win);
5105 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5106 FALSE)); /* don't create */
5108 /* Get the folder view widget if exists */
5110 folder_view = modest_main_window_get_child_widget (main_window,
5111 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5115 /* Create and run the dialog */
5116 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5117 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5118 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5119 result = gtk_dialog_run (GTK_DIALOG(dialog));
5120 g_object_ref (tree_view);
5121 gtk_widget_destroy (dialog);
5123 if (result != GTK_RESPONSE_ACCEPT)
5126 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5127 /* Do window specific stuff */
5128 if (MODEST_IS_MAIN_WINDOW (win)) {
5129 modest_ui_actions_on_main_window_move_to (action,
5132 MODEST_MAIN_WINDOW (win));
5134 modest_ui_actions_on_msg_view_window_move_to (action,
5136 MODEST_MSG_VIEW_WINDOW (win));
5140 g_object_unref (dst_folder);
5144 * Calls #HeadersFunc for each header already selected in the main
5145 * window or the message currently being shown in the msg view window
5148 do_headers_action (ModestWindow *win,
5152 TnyList *headers_list = NULL;
5153 TnyIterator *iter = NULL;
5154 TnyHeader *header = NULL;
5155 TnyFolder *folder = NULL;
5158 headers_list = get_selected_headers (win);
5162 /* Get the folder */
5163 iter = tny_list_create_iterator (headers_list);
5164 header = TNY_HEADER (tny_iterator_get_current (iter));
5166 folder = tny_header_get_folder (header);
5167 g_object_unref (header);
5170 /* Call the function for each header */
5171 while (!tny_iterator_is_done (iter)) {
5172 header = TNY_HEADER (tny_iterator_get_current (iter));
5173 func (header, win, user_data);
5174 g_object_unref (header);
5175 tny_iterator_next (iter);
5178 /* Trick: do a poke status in order to speed up the signaling
5180 tny_folder_poke_status (folder);
5183 g_object_unref (folder);
5184 g_object_unref (iter);
5185 g_object_unref (headers_list);
5189 modest_ui_actions_view_attachment (GtkAction *action,
5190 ModestWindow *window)
5192 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5193 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5195 /* not supported window for this action */
5196 g_return_if_reached ();
5201 modest_ui_actions_save_attachments (GtkAction *action,
5202 ModestWindow *window)
5204 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5205 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5207 /* not supported window for this action */
5208 g_return_if_reached ();
5213 modest_ui_actions_remove_attachments (GtkAction *action,
5214 ModestWindow *window)
5216 if (MODEST_IS_MAIN_WINDOW (window)) {
5217 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5218 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5219 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5221 /* not supported window for this action */
5222 g_return_if_reached ();
5227 modest_ui_actions_on_settings (GtkAction *action,
5232 dialog = modest_platform_get_global_settings_dialog ();
5233 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5234 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5235 gtk_widget_show_all (dialog);
5237 gtk_dialog_run (GTK_DIALOG (dialog));
5239 gtk_widget_destroy (dialog);
5243 modest_ui_actions_on_help (GtkAction *action,
5246 const gchar *help_id;
5248 g_return_if_fail (action);
5249 g_return_if_fail (win && GTK_IS_WINDOW(win));
5251 help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5254 modest_platform_show_help (GTK_WINDOW (win), help_id);
5256 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5260 retrieve_msg_contents_performer (gboolean canceled,
5262 GtkWindow *parent_window,
5263 TnyAccount *account,
5266 ModestMailOperation *mail_op;
5267 TnyList *headers = TNY_LIST (user_data);
5269 if (err || canceled) {
5273 /* Create mail operation */
5274 mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5275 modest_ui_actions_disk_operations_error_handler,
5277 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5278 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5281 g_object_unref (mail_op);
5283 g_object_unref (headers);
5284 g_object_unref (account);
5288 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5289 ModestWindow *window)
5291 TnyList *headers = NULL;
5292 TnyAccount *account = NULL;
5293 TnyIterator *iter = NULL;
5294 TnyHeader *header = NULL;
5295 TnyFolder *folder = NULL;
5298 headers = get_selected_headers (window);
5302 /* Pick the account */
5303 iter = tny_list_create_iterator (headers);
5304 header = TNY_HEADER (tny_iterator_get_current (iter));
5305 folder = tny_header_get_folder (header);
5306 account = tny_folder_get_account (folder);
5307 g_object_unref (folder);
5308 g_object_unref (header);
5309 g_object_unref (iter);
5311 /* Connect and perform the message retrieval */
5312 modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5313 g_object_ref (account),
5314 retrieve_msg_contents_performer,
5315 g_object_ref (headers));
5318 g_object_unref (account);
5319 g_object_unref (headers);
5323 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5325 g_return_if_fail (MODEST_IS_WINDOW (window));
5328 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5332 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5334 g_return_if_fail (MODEST_IS_WINDOW (window));
5337 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5341 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5342 ModestWindow *window)
5344 g_return_if_fail (MODEST_IS_WINDOW (window));
5347 modest_ui_actions_check_menu_dimming_rules (window);
5351 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5352 ModestWindow *window)
5354 g_return_if_fail (MODEST_IS_WINDOW (window));
5357 modest_ui_actions_check_menu_dimming_rules (window);
5361 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5362 ModestWindow *window)
5364 g_return_if_fail (MODEST_IS_WINDOW (window));
5367 modest_ui_actions_check_menu_dimming_rules (window);
5371 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5372 ModestWindow *window)
5374 g_return_if_fail (MODEST_IS_WINDOW (window));
5377 modest_ui_actions_check_menu_dimming_rules (window);
5381 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5382 ModestWindow *window)
5384 g_return_if_fail (MODEST_IS_WINDOW (window));
5387 modest_ui_actions_check_menu_dimming_rules (window);
5391 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5392 ModestWindow *window)
5394 g_return_if_fail (MODEST_IS_WINDOW (window));
5397 modest_ui_actions_check_menu_dimming_rules (window);
5401 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5402 ModestWindow *window)
5404 g_return_if_fail (MODEST_IS_WINDOW (window));
5407 modest_ui_actions_check_menu_dimming_rules (window);
5411 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5412 ModestWindow *window)
5414 g_return_if_fail (MODEST_IS_WINDOW (window));
5417 modest_ui_actions_check_menu_dimming_rules (window);
5421 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5422 ModestWindow *window)
5424 g_return_if_fail (MODEST_IS_WINDOW (window));
5427 modest_ui_actions_check_menu_dimming_rules (window);
5431 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5433 g_return_if_fail (MODEST_IS_WINDOW (window));
5435 modest_platform_show_search_messages (GTK_WINDOW (window));
5439 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5441 g_return_if_fail (MODEST_IS_WINDOW (win));
5442 modest_platform_show_addressbook (GTK_WINDOW (win));
5447 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5448 ModestWindow *window)
5450 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5452 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5456 on_send_receive_finished (ModestMailOperation *mail_op,
5459 GtkWidget *header_view, *folder_view;
5460 TnyFolderStore *folder_store;
5461 ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5463 /* Set send/receive operation finished */
5464 modest_main_window_notify_send_receive_completed (main_win);
5466 /* Don't refresh the current folder if there were any errors */
5467 if (modest_mail_operation_get_status (mail_op) !=
5468 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5471 /* Refresh the current folder if we're viewing a window. We do
5472 this because the user won't be able to see the new mails in
5473 the selected folder after a Send&Receive because it only
5474 performs a poke_status, i.e, only the number of read/unread
5475 messages is updated, but the new headers are not
5477 folder_view = modest_main_window_get_child_widget (main_win,
5478 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5482 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5484 /* Do not need to refresh INBOX again because the
5485 update_account does it always automatically */
5486 if (folder_store && TNY_IS_FOLDER (folder_store) &&
5487 tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5488 ModestMailOperation *refresh_op;
5490 header_view = modest_main_window_get_child_widget (main_win,
5491 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5493 /* We do not need to set the contents style
5494 because it hasn't changed. We also do not
5495 need to save the widget status. Just force
5497 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5498 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5499 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5500 folder_refreshed_cb, main_win);
5501 g_object_unref (refresh_op);
5505 g_object_unref (folder_store);
5510 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5516 const gchar* server_name = NULL;
5517 TnyTransportAccount *server_account;
5518 gchar *message = NULL;
5520 /* Don't show anything if the user cancelled something or the send receive request is not
5522 if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5523 !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5527 /* Get the server name: */
5529 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5531 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5533 g_return_if_reached ();
5535 /* Show the appropriate message text for the GError: */
5536 switch (err->code) {
5537 case TNY_SERVICE_ERROR_CONNECT:
5538 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5540 case TNY_SERVICE_ERROR_AUTHENTICATE:
5541 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5543 case TNY_SERVICE_ERROR_SEND:
5544 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5546 case TNY_SERVICE_ERROR_UNAVAILABLE:
5547 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5550 g_warning ("%s: unexpected ERROR %d",
5551 __FUNCTION__, err->code);
5552 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5556 /* TODO if the username or the password where not defined we
5557 should show the Accounts Settings dialog or the Connection
5558 specific SMTP server window */
5560 modest_platform_run_information_dialog (NULL, message);
5562 g_object_unref (server_account);
5566 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5571 ModestMainWindow *main_window = NULL;
5572 ModestWindowMgr *mgr = NULL;
5573 GtkWidget *folder_view = NULL, *header_view = NULL;
5574 TnyFolderStore *selected_folder = NULL;
5575 TnyFolderType folder_type;
5577 mgr = modest_runtime_get_window_mgr ();
5578 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5579 FALSE));/* don't create */
5583 /* Check if selected folder is OUTBOX */
5584 folder_view = modest_main_window_get_child_widget (main_window,
5585 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5586 header_view = modest_main_window_get_child_widget (main_window,
5587 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5589 selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5590 if (!TNY_IS_FOLDER (selected_folder))
5593 /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5594 #if GTK_CHECK_VERSION(2, 8, 0)
5595 folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder));
5596 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
5597 GtkTreeViewColumn *tree_column;
5599 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5600 TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5601 gtk_tree_view_column_queue_resize (tree_column);
5604 gtk_widget_queue_draw (header_view);
5607 /* Rerun dimming rules, because the message could become deletable for example */
5608 modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window),
5609 MODEST_DIMMING_RULES_TOOLBAR);
5613 if (selected_folder != NULL)
5614 g_object_unref (selected_folder);
5618 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5619 TnyAccount *account)
5621 ModestTransportStoreProtocol proto;
5622 const gchar *proto_name;
5623 gchar *error_note = NULL;
5625 proto_name = tny_account_get_proto (account);
5626 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5629 case MODEST_PROTOCOL_STORE_POP:
5630 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"),
5631 tny_account_get_hostname (account));
5633 case MODEST_PROTOCOL_STORE_IMAP:
5634 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"),
5635 tny_account_get_hostname (account));
5637 case MODEST_PROTOCOL_STORE_MAILDIR:
5638 case MODEST_PROTOCOL_STORE_MBOX:
5639 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5642 g_warning ("%s: This should not be reached", __FUNCTION__);
5646 modest_platform_run_information_dialog (parent_window, error_note);
5647 g_free (error_note);
5652 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5655 TnyFolderStore *folder = NULL;
5656 TnyAccount *account = NULL;
5657 ModestTransportStoreProtocol proto;
5658 TnyHeader *header = NULL;
5660 if (MODEST_IS_MAIN_WINDOW (win)) {
5661 GtkWidget *header_view;
5662 TnyList* headers = NULL;
5664 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5665 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5666 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5667 if (!headers || tny_list_get_length (headers) == 0) {
5669 g_object_unref (headers);
5672 iter = tny_list_create_iterator (headers);
5673 header = TNY_HEADER (tny_iterator_get_current (iter));
5674 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5675 g_object_unref (iter);
5676 g_object_unref (headers);
5677 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5678 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5679 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5682 /* Get the account type */
5683 account = tny_folder_get_account (TNY_FOLDER (folder));
5684 proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5685 if (proto == MODEST_PROTOCOL_STORE_POP) {
5686 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5687 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5688 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
5689 tny_header_get_subject (header));
5691 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5695 g_object_unref (account);
5696 g_object_unref (folder);
5697 g_object_unref (header);