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);
168 * This function checks whether a TnyFolderStore is a pop account
171 remote_folder_is_pop (TnyFolderStore *folder)
173 const gchar *proto = NULL;
174 TnyAccount *account = NULL;
176 g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
178 account = get_account_from_folder_store (folder);
179 proto = tny_account_get_proto (account);
180 g_object_unref (account);
182 return (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
185 /* FIXME: this should be merged with the similar code in modest-account-view-window */
186 /* Show the account creation wizard dialog.
187 * returns: TRUE if an account was created. FALSE if the user cancelled.
190 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
192 gboolean result = FALSE;
193 GtkWindow *dialog, *wizard;
194 gint dialog_response;
196 /* Show the easy-setup wizard: */
197 dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
199 /* old wizard is active already;
201 gtk_window_present (GTK_WINDOW(dialog));
206 /* there is no such wizard yet */
207 wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
208 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
210 /* always present a main window in the background
211 * we do it here, so we cannot end up with two wizards (as this
212 * function might be called in modest_window_mgr_get_main_window as well */
214 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
215 TRUE); /* create if not existent */
217 /* make sure the mainwindow is visible */
218 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
219 gtk_widget_show_all (GTK_WIDGET(win));
220 gtk_window_present (GTK_WINDOW(win));
222 dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
223 gtk_widget_destroy (GTK_WIDGET (wizard));
224 if (gtk_events_pending ())
225 gtk_main_iteration ();
227 if (dialog_response == GTK_RESPONSE_CANCEL) {
230 /* Check whether an account was created: */
231 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
238 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
241 const gchar *authors[] = {
242 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
245 about = gtk_about_dialog_new ();
246 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
247 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
248 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
249 _("Copyright (c) 2006, Nokia Corporation\n"
250 "All rights reserved."));
251 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
252 _("a modest e-mail client\n\n"
253 "design and implementation: Dirk-Jan C. Binnema\n"
254 "contributions from the fine people at KC and Ig\n"
255 "uses the tinymail email framework written by Philip van Hoof"));
256 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
257 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
258 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
259 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
261 gtk_dialog_run (GTK_DIALOG (about));
262 gtk_widget_destroy(about);
266 * Gets the list of currently selected messages. If the win is the
267 * main window, then it returns a newly allocated list of the headers
268 * selected in the header view. If win is the msg view window, then
269 * the value returned is a list with just a single header.
271 * The caller of this funcion must free the list.
274 get_selected_headers (ModestWindow *win)
276 if (MODEST_IS_MAIN_WINDOW(win)) {
277 GtkWidget *header_view;
279 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
280 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
281 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
283 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
284 /* for MsgViewWindows, we simply return a list with one element */
286 TnyList *list = NULL;
288 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
289 if (header != NULL) {
290 list = tny_simple_list_new ();
291 tny_list_prepend (list, G_OBJECT(header));
292 g_object_unref (G_OBJECT(header));
301 static GtkTreeRowReference *
302 get_next_after_selected_headers (ModestHeaderView *header_view)
304 GtkTreeSelection *sel;
305 GList *selected_rows, *node;
307 GtkTreeRowReference *result;
310 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
311 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
312 selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
314 if (selected_rows == NULL)
317 node = g_list_last (selected_rows);
318 path = gtk_tree_path_copy ((GtkTreePath *) node->data);
319 gtk_tree_path_next (path);
321 result = gtk_tree_row_reference_new (model, path);
323 gtk_tree_path_free (path);
324 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
325 g_list_free (selected_rows);
331 headers_action_mark_as_read (TnyHeader *header,
335 TnyHeaderFlags flags;
337 g_return_if_fail (TNY_IS_HEADER(header));
339 flags = tny_header_get_flags (header);
340 if (flags & TNY_HEADER_FLAG_SEEN) return;
341 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
345 headers_action_mark_as_unread (TnyHeader *header,
349 TnyHeaderFlags flags;
351 g_return_if_fail (TNY_IS_HEADER(header));
353 flags = tny_header_get_flags (header);
354 if (flags & TNY_HEADER_FLAG_SEEN) {
355 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
359 /** After deleing a message that is currently visible in a window,
360 * show the next message from the list, or close the window if there are no more messages.
363 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
365 /* Close msg view window or select next */
366 if (!modest_msg_view_window_select_next_message (win) &&
367 !modest_msg_view_window_select_previous_message (win)) {
369 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
375 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
377 TnyList *header_list = NULL;
378 TnyIterator *iter = NULL;
379 TnyHeader *header = NULL;
380 gchar *message = NULL;
383 ModestWindowMgr *mgr;
384 GtkWidget *header_view = NULL;
386 g_return_if_fail (MODEST_IS_WINDOW(win));
388 /* Check first if the header view has the focus */
389 if (MODEST_IS_MAIN_WINDOW (win)) {
391 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
392 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
393 if (!gtk_widget_is_focus (header_view))
397 /* Get the headers, either from the header view (if win is the main window),
398 * or from the message view window: */
399 header_list = get_selected_headers (win);
400 if (!header_list) return;
402 /* Check if any of the headers are already opened, or in the process of being opened */
403 if (MODEST_IS_MAIN_WINDOW (win)) {
404 gint opened_headers = 0;
406 iter = tny_list_create_iterator (header_list);
407 mgr = modest_runtime_get_window_mgr ();
408 while (!tny_iterator_is_done (iter)) {
409 header = TNY_HEADER (tny_iterator_get_current (iter));
411 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
413 g_object_unref (header);
415 tny_iterator_next (iter);
417 g_object_unref (iter);
419 if (opened_headers > 0) {
422 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
425 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
428 g_object_unref (header_list);
434 if (tny_list_get_length(header_list) == 1) {
435 iter = tny_list_create_iterator (header_list);
436 header = TNY_HEADER (tny_iterator_get_current (iter));
439 subject = tny_header_dup_subject (header);
440 desc = g_strdup_printf ("%s", subject);
442 g_object_unref (header);
445 g_object_unref (iter);
447 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
448 tny_list_get_length(header_list)), desc);
450 /* Confirmation dialog */
451 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
455 if (response == GTK_RESPONSE_OK) {
456 ModestWindow *main_window = NULL;
457 ModestWindowMgr *mgr = NULL;
458 GtkTreeModel *model = NULL;
459 GtkTreeSelection *sel = NULL;
460 GList *sel_list = NULL, *tmp = NULL;
461 GtkTreeRowReference *next_row_reference = NULL;
462 GtkTreeRowReference *prev_row_reference = NULL;
463 GtkTreePath *next_path = NULL;
464 GtkTreePath *prev_path = NULL;
465 ModestMailOperation *mail_op = NULL;
467 /* Find last selected row */
468 if (MODEST_IS_MAIN_WINDOW (win)) {
469 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
470 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
471 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
472 for (tmp=sel_list; tmp; tmp=tmp->next) {
473 if (tmp->next == NULL) {
474 prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
475 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
477 gtk_tree_path_prev (prev_path);
478 gtk_tree_path_next (next_path);
480 prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
481 next_row_reference = gtk_tree_row_reference_new (model, next_path);
486 /* Disable window dimming management */
487 modest_window_disable_dimming (MODEST_WINDOW(win));
489 /* Remove each header. If it's a view window header_view == NULL */
490 mail_op = modest_mail_operation_new ((GObject *) win);
491 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
493 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
494 g_object_unref (mail_op);
496 /* Enable window dimming management */
498 gtk_tree_selection_unselect_all (sel);
500 modest_window_enable_dimming (MODEST_WINDOW(win));
502 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
503 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
505 /* Get main window */
506 mgr = modest_runtime_get_window_mgr ();
507 main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
509 /* Move cursor to next row */
512 /* Select next or previous row */
513 if (gtk_tree_row_reference_valid (next_row_reference)) {
514 /* next_path = gtk_tree_row_reference_get_path (row_reference); */
515 gtk_tree_selection_select_path (sel, next_path);
517 else if (gtk_tree_row_reference_valid (prev_row_reference)) {
518 gtk_tree_selection_select_path (sel, prev_path);
522 if (next_row_reference != NULL)
523 gtk_tree_row_reference_free (next_row_reference);
524 if (next_path != NULL)
525 gtk_tree_path_free (next_path);
526 if (prev_row_reference != NULL)
527 gtk_tree_row_reference_free (prev_row_reference);
528 if (prev_path != NULL)
529 gtk_tree_path_free (prev_path);
532 /* Update toolbar dimming state */
534 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
537 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
538 g_list_free (sel_list);
544 g_object_unref (header_list);
550 /* delete either message or folder, based on where we are */
552 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
554 g_return_if_fail (MODEST_IS_WINDOW(win));
556 /* Check first if the header view has the focus */
557 if (MODEST_IS_MAIN_WINDOW (win)) {
559 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
560 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
561 if (gtk_widget_is_focus (w)) {
562 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
566 modest_ui_actions_on_delete_message (action, win);
570 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
572 ModestWindowMgr *mgr = NULL;
574 #ifdef MODEST_PLATFORM_MAEMO
575 modest_osso_save_state();
576 #endif /* MODEST_PLATFORM_MAEMO */
578 g_debug ("closing down, clearing %d item(s) from operation queue",
579 modest_mail_operation_queue_num_elements
580 (modest_runtime_get_mail_operation_queue()));
582 /* cancel all outstanding operations */
583 modest_mail_operation_queue_cancel_all
584 (modest_runtime_get_mail_operation_queue());
586 g_debug ("queue has been cleared");
589 /* Check if there are opened editing windows */
590 mgr = modest_runtime_get_window_mgr ();
591 modest_window_mgr_close_all_windows (mgr);
593 /* note: when modest-tny-account-store is finalized,
594 it will automatically set all network connections
597 /* gtk_main_quit (); */
601 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
605 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
607 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
608 /* gtk_widget_destroy (GTK_WIDGET (win)); */
609 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
610 /* gboolean ret_value; */
611 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
612 /* } else if (MODEST_IS_WINDOW (win)) { */
613 /* gtk_widget_destroy (GTK_WIDGET (win)); */
615 /* g_return_if_reached (); */
620 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
622 GtkClipboard *clipboard = NULL;
623 gchar *selection = NULL;
625 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
626 selection = gtk_clipboard_wait_for_text (clipboard);
628 /* Question: why is the clipboard being used here?
629 * It doesn't really make a lot of sense. */
633 modest_address_book_add_address (selection);
639 modest_ui_actions_on_accounts (GtkAction *action,
642 /* This is currently only implemented for Maemo */
643 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
644 if (!modest_ui_actions_run_account_setup_wizard (win))
645 g_debug ("%s: wizard was already running", __FUNCTION__);
649 /* Show the list of accounts */
650 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
652 /* The accounts dialog must be modal */
653 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
654 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
658 #ifdef MODEST_PLATFORM_MAEMO
660 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
662 /* Save any changes. */
663 modest_connection_specific_smtp_window_save_server_accounts (
664 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
665 gtk_widget_destroy (GTK_WIDGET (window));
671 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
673 /* This is currently only implemented for Maemo,
674 * because it requires an API (libconic) to detect different connection
677 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
679 /* Create the window if necessary: */
680 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
681 modest_connection_specific_smtp_window_fill_with_connections (
682 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
683 modest_runtime_get_account_mgr());
685 /* Show the window: */
686 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
687 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
688 gtk_widget_show (specific_window);
690 /* Save changes when the window is hidden: */
691 g_signal_connect (specific_window, "hide",
692 G_CALLBACK (on_smtp_servers_window_hide), win);
693 #endif /* MODEST_PLATFORM_MAEMO */
697 modest_ui_actions_compose_msg(ModestWindow *win,
700 const gchar *bcc_str,
701 const gchar *subject_str,
702 const gchar *body_str,
704 gboolean set_as_modified)
706 gchar *account_name = NULL;
708 TnyAccount *account = NULL;
709 TnyFolder *folder = NULL;
710 gchar *from_str = NULL, *signature = NULL, *body = NULL;
711 gboolean use_signature = FALSE;
712 ModestWindow *msg_win = NULL;
713 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
714 ModestTnyAccountStore *store = modest_runtime_get_account_store();
715 GnomeVFSFileSize total_size, allowed_size;
717 /* we check for low-mem; in that case, show a warning, and don't allow
718 * composing a message with attachments
720 if (attachments && modest_platform_check_memory_low (win))
723 account_name = modest_account_mgr_get_default_account(mgr);
725 g_printerr ("modest: no account found\n");
728 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
730 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
733 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
735 g_printerr ("modest: failed to find Drafts folder\n");
738 from_str = modest_account_mgr_get_from_string (mgr, account_name);
740 g_printerr ("modest: failed get from string for '%s'\n", account_name);
744 signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
745 if (body_str != NULL) {
746 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
748 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
751 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL, NULL);
753 g_printerr ("modest: failed to create new msg\n");
757 /* Create and register edit window */
758 /* This is destroyed by TODO. */
760 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
761 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
762 while (attachments) {
764 modest_msg_edit_window_attach_file_one(
765 (ModestMsgEditWindow *)msg_win,
766 attachments->data, allowed_size);
768 if (total_size > allowed_size) {
769 g_warning ("%s: total size: %u",
770 __FUNCTION__, (unsigned int)total_size);
773 allowed_size -= total_size;
775 attachments = g_slist_next(attachments);
777 modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
778 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
780 gtk_widget_show_all (GTK_WIDGET (msg_win));
786 g_free (account_name);
788 g_object_unref (G_OBJECT(account));
790 g_object_unref (G_OBJECT(folder));
792 g_object_unref (G_OBJECT(msg_win));
794 g_object_unref (G_OBJECT(msg));
798 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
800 /* if there are no accounts yet, just show the wizard */
801 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
802 if (!modest_ui_actions_run_account_setup_wizard (win))
805 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
810 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
814 ModestMailOperationStatus status;
816 /* If there is no message or the operation was not successful */
817 status = modest_mail_operation_get_status (mail_op);
818 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
820 /* Remove the header from the preregistered uids */
821 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
839 OpenMsgBannerInfo *banner_info;
840 GHashTable *row_refs_per_header;
844 open_msg_banner_idle (gpointer userdata)
846 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
848 gdk_threads_enter ();
849 banner_info->idle_handler = 0;
850 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
852 g_object_ref (banner_info->banner);
854 gdk_threads_leave ();
861 open_msg_cb (ModestMailOperation *mail_op,
868 ModestWindowMgr *mgr = NULL;
869 ModestWindow *parent_win = NULL;
870 ModestWindow *win = NULL;
871 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
872 gchar *account = NULL;
874 gboolean open_in_editor = FALSE;
875 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
877 /* Do nothing if there was any problem with the mail
878 operation. The error will be shown by the error_handler of
879 the mail operation */
880 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
883 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
884 folder = tny_header_get_folder (header);
886 /* Mark header as read */
887 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
889 /* Gets folder type (OUTBOX headers will be opened in edit window */
890 if (modest_tny_folder_is_local_folder (folder)) {
891 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
892 if (folder_type == TNY_FOLDER_TYPE_INVALID)
893 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
897 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
898 TnyTransportAccount *traccount = NULL;
899 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
900 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
902 ModestTnySendQueue *send_queue = NULL;
903 ModestTnySendQueueStatus status;
905 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
906 TNY_ACCOUNT(traccount)));
907 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
908 msg_id = modest_tny_send_queue_get_msg_id (header);
909 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
910 /* Only open messages in outbox with the editor if they are in Failed state */
911 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
912 open_in_editor = TRUE;
915 g_object_unref(traccount);
917 g_warning("Cannot get transport account for message in outbox!!");
919 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
920 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
925 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
927 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
929 if (open_in_editor) {
930 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
931 gchar *from_header = NULL;
933 from_header = tny_header_dup_from (header);
935 /* we cannot edit without a valid account... */
936 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
937 if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
938 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
940 g_free (from_header);
946 GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
948 gchar *from_header_email;
950 from_header_email = modest_text_utils_get_email_address ((const gchar *) from_header);
952 for (node = accounts; node != NULL; node = g_slist_next (node)) {
953 gchar *from, *from_email;
955 from = modest_account_mgr_get_from_string (mgr, node->data);
957 from_email = modest_text_utils_get_email_address ((const gchar *) from);
958 if (strcmp (from_header_email, from_email) == 0) {
960 account = g_strdup (node->data);
969 g_free (from_header_email);
970 g_free (from_header);
971 g_slist_foreach (accounts, (GFunc) g_free, NULL);
972 g_slist_free (accounts);
975 win = modest_msg_edit_window_new (msg, account, TRUE);
980 gchar *uid = modest_tny_folder_get_header_unique_id (header);
982 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
983 GtkTreeRowReference *row_reference;
985 row_reference = (GtkTreeRowReference *) g_hash_table_lookup (helper->row_refs_per_header, header);
987 win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
988 helper->model, row_reference);
990 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
995 /* Register and show new window */
997 mgr = modest_runtime_get_window_mgr ();
998 modest_window_mgr_register_window (mgr, win);
999 g_object_unref (win);
1000 gtk_widget_show_all (GTK_WIDGET(win));
1003 /* Update toolbar dimming state */
1004 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1005 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1011 g_object_unref (parent_win);
1012 g_object_unref (folder);
1016 is_memory_full_error (GError *error)
1018 if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
1019 error->code == TNY_IO_ERROR_WRITE ||
1020 error->code == TNY_IO_ERROR_READ) {
1028 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1031 const GError *error;
1032 GObject *win = NULL;
1033 ModestMailOperationStatus status;
1035 win = modest_mail_operation_get_source (mail_op);
1036 error = modest_mail_operation_get_error (mail_op);
1037 status = modest_mail_operation_get_status (mail_op);
1039 /* If the mail op has been cancelled then it's not an error:
1040 don't show any message */
1041 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1042 if (is_memory_full_error ((GError *) error)) {
1043 modest_platform_information_banner ((GtkWidget *) win,
1044 NULL, dgettext("ke-recv",
1045 "cerm_device_memory_full"));
1046 } else if (error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1047 modest_platform_information_banner ((GtkWidget *) win,
1048 NULL, dgettext ("hildon-common-strings", "sfil_ni_unable_to_open_file_not_found"));
1049 } else if (user_data) {
1050 modest_platform_information_banner ((GtkWidget *) win,
1056 g_object_unref (win);
1060 * Returns the account a list of headers belongs to. It returns a
1061 * *new* reference so don't forget to unref it
1064 get_account_from_header_list (TnyList *headers)
1066 TnyAccount *account = NULL;
1068 if (tny_list_get_length (headers) > 0) {
1069 TnyIterator *iter = tny_list_create_iterator (headers);
1070 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1071 TnyFolder *folder = tny_header_get_folder (header);
1074 g_object_unref (header);
1076 while (!tny_iterator_is_done (iter)) {
1077 header = TNY_HEADER (tny_iterator_get_current (iter));
1078 folder = tny_header_get_folder (header);
1081 g_object_unref (header);
1083 tny_iterator_next (iter);
1088 account = tny_folder_get_account (folder);
1089 g_object_unref (folder);
1093 g_object_unref (header);
1095 g_object_unref (iter);
1101 foreach_unregister_headers (gpointer data,
1104 ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1105 TnyHeader *header = TNY_HEADER (data);
1107 modest_window_mgr_unregister_header (mgr, header);
1111 open_msgs_helper_destroyer (gpointer user_data)
1113 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1115 if (helper->banner_info) {
1116 g_free (helper->banner_info->message);
1117 if (helper->banner_info->idle_handler > 0) {
1118 g_source_remove (helper->banner_info->idle_handler);
1119 helper->banner_info->idle_handler = 0;
1121 if (helper->banner_info->banner != NULL) {
1122 gtk_widget_destroy (helper->banner_info->banner);
1123 g_object_unref (helper->banner_info->banner);
1124 helper->banner_info->banner = NULL;
1126 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1127 helper->banner_info = NULL;
1129 g_object_unref (helper->model);
1130 g_object_unref (helper->headers);
1131 g_hash_table_destroy (helper->row_refs_per_header);
1132 g_slice_free (OpenMsgHelper, helper);
1136 open_msgs_performer(gboolean canceled,
1138 GtkWindow *parent_window,
1139 TnyAccount *account,
1142 ModestMailOperation *mail_op = NULL;
1143 const gchar *proto_name;
1145 ModestTransportStoreProtocol proto;
1146 TnyList *not_opened_headers;
1147 TnyConnectionStatus status;
1148 gboolean show_open_draft = FALSE;
1149 OpenMsgHelper *helper = NULL;
1151 helper = (OpenMsgHelper *) user_data;
1152 not_opened_headers = helper->headers;
1154 status = tny_account_get_connection_status (account);
1155 if (err || canceled) {
1156 /* Unregister the already registered headers */
1157 tny_list_foreach (not_opened_headers, foreach_unregister_headers,
1158 modest_runtime_get_window_mgr ());
1159 /* Free the helper */
1160 open_msgs_helper_destroyer (helper);
1162 /* In memory full conditions we could get this error here */
1163 if (err && is_memory_full_error (err)) {
1164 modest_platform_information_banner ((GtkWidget *) parent_window,
1165 NULL, dgettext("ke-recv",
1166 "cerm_device_memory_full"));
1171 /* Get the error message depending on the protocol */
1172 proto_name = tny_account_get_proto (account);
1173 if (proto_name != NULL) {
1174 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1176 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1179 /* Create the error messages */
1180 if (tny_list_get_length (not_opened_headers) == 1) {
1181 if (proto == MODEST_PROTOCOL_STORE_POP) {
1182 error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1183 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1184 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1185 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1186 gchar *subject = tny_header_dup_subject (header);
1187 error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1190 g_object_unref (header);
1191 g_object_unref (iter);
1196 TnyFolderType folder_type;
1198 iter = tny_list_create_iterator (not_opened_headers);
1199 header = TNY_HEADER (tny_iterator_get_current (iter));
1200 folder = tny_header_get_folder (header);
1201 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1202 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1203 g_object_unref (folder);
1204 g_object_unref (header);
1205 g_object_unref (iter);
1206 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1209 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1212 /* Create the mail operation */
1214 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1215 modest_ui_actions_disk_operations_error_handler,
1217 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1220 if (show_open_draft) {
1221 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1222 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1223 helper->banner_info->banner = NULL;
1224 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1225 helper->banner_info);
1228 modest_mail_operation_get_msgs_full (mail_op,
1232 open_msgs_helper_destroyer);
1237 g_object_unref (mail_op);
1238 g_object_unref (account);
1242 * This function is used by both modest_ui_actions_on_open and
1243 * modest_ui_actions_on_header_activated. This way we always do the
1244 * same when trying to open messages.
1247 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1249 ModestWindowMgr *mgr = NULL;
1250 TnyIterator *iter = NULL, *iter_not_opened = NULL;
1251 TnyList *not_opened_headers = NULL;
1252 TnyHeaderFlags flags = 0;
1253 TnyAccount *account;
1254 gint uncached_msgs = 0;
1255 GtkWidget *header_view;
1256 GtkTreeModel *model;
1257 GHashTable *refs_for_headers;
1258 OpenMsgHelper *helper;
1259 GtkTreeSelection *sel;
1260 GList *sel_list = NULL, *sel_list_iter = NULL;
1262 g_return_if_fail (headers != NULL);
1264 /* Check that only one message is selected for opening */
1265 if (tny_list_get_length (headers) != 1) {
1266 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1267 NULL, _("mcen_ib_select_one_message"));
1271 mgr = modest_runtime_get_window_mgr ();
1272 iter = tny_list_create_iterator (headers);
1274 /* Get the account */
1275 account = get_account_from_header_list (headers);
1280 /* Get the selections, we need to get the references to the
1281 rows here because the treeview/model could dissapear (the
1282 user might want to select another folder)*/
1283 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1284 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1285 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1286 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
1287 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1288 refs_for_headers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1289 (GDestroyNotify) gtk_tree_row_reference_free);
1291 /* Look if we already have a message view for each header. If
1292 true, then remove the header from the list of headers to
1294 sel_list_iter = sel_list;
1295 not_opened_headers = tny_simple_list_new ();
1296 while (!tny_iterator_is_done (iter) && sel_list_iter) {
1298 ModestWindow *window = NULL;
1299 TnyHeader *header = NULL;
1300 gboolean found = FALSE;
1302 header = TNY_HEADER (tny_iterator_get_current (iter));
1304 flags = tny_header_get_flags (header);
1307 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1309 /* Do not open again the message and present the
1310 window to the user */
1313 gtk_window_present (GTK_WINDOW (window));
1315 /* the header has been registered already, we don't do
1316 * anything but wait for the window to come up*/
1317 g_debug ("header %p already registered, waiting for window", header);
1320 GtkTreeRowReference *row_reference;
1322 tny_list_append (not_opened_headers, G_OBJECT (header));
1323 /* Create a new row reference and add it to the hash table */
1324 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list_iter->data);
1325 g_hash_table_insert (refs_for_headers, header, row_reference);
1329 g_object_unref (header);
1332 tny_iterator_next (iter);
1333 sel_list_iter = g_list_next (sel_list_iter);
1335 g_object_unref (iter);
1337 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1338 g_list_free (sel_list);
1340 /* Open each message */
1341 if (tny_list_get_length (not_opened_headers) == 0) {
1342 g_hash_table_destroy (refs_for_headers);
1346 /* If some messages would have to be downloaded, ask the user to
1347 * make a connection. It's generally easier to do this here (in the mainloop)
1348 * than later in a thread:
1350 if (tny_list_get_length (not_opened_headers) > 0) {
1351 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1353 if (uncached_msgs > 0) {
1354 /* Allways download if we are online. */
1355 if (!tny_device_is_online (modest_runtime_get_device ())) {
1358 /* If ask for user permission to download the messages */
1359 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1360 ngettext("mcen_nc_get_msg",
1364 /* End if the user does not want to continue */
1365 if (response == GTK_RESPONSE_CANCEL) {
1366 g_hash_table_destroy (refs_for_headers);
1373 /* Register the headers before actually creating the windows: */
1374 iter_not_opened = tny_list_create_iterator (not_opened_headers);
1375 while (!tny_iterator_is_done (iter_not_opened)) {
1376 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1378 modest_window_mgr_register_header (mgr, header, NULL);
1379 g_object_unref (header);
1381 tny_iterator_next (iter_not_opened);
1383 g_object_unref (iter_not_opened);
1384 iter_not_opened = NULL;
1386 /* Create the helper. We need to get a reference to the model
1387 here because it could change while the message is readed
1388 (the user could switch between folders) */
1389 helper = g_slice_new (OpenMsgHelper);
1390 helper->model = g_object_ref (model);
1391 helper->headers = g_object_ref (not_opened_headers);
1392 helper->row_refs_per_header = refs_for_headers;
1393 helper->banner_info = NULL;
1395 /* Connect to the account and perform */
1396 if (uncached_msgs > 0) {
1397 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1398 open_msgs_performer, helper);
1400 /* Call directly the performer, do not need to connect */
1401 open_msgs_performer (FALSE, NULL, (GtkWindow *) win,
1402 g_object_ref (account), helper);
1407 g_object_unref (account);
1408 if (not_opened_headers)
1409 g_object_unref (not_opened_headers);
1413 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1417 /* we check for low-mem; in that case, show a warning, and don't allow
1420 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1424 headers = get_selected_headers (win);
1429 open_msgs_from_headers (headers, win);
1431 g_object_unref(headers);
1436 free_reply_forward_helper (gpointer data)
1438 ReplyForwardHelper *helper;
1440 helper = (ReplyForwardHelper *) data;
1441 g_free (helper->account_name);
1442 g_slice_free (ReplyForwardHelper, helper);
1446 reply_forward_cb (ModestMailOperation *mail_op,
1454 ReplyForwardHelper *rf_helper;
1455 ModestWindow *msg_win = NULL;
1456 ModestEditType edit_type;
1458 TnyAccount *account = NULL;
1459 ModestWindowMgr *mgr = NULL;
1460 gchar *signature = NULL;
1461 gboolean use_signature;
1463 /* If there was any error. The mail operation could be NULL,
1464 this means that we already have the message downloaded and
1465 that we didn't do a mail operation to retrieve it */
1466 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1469 g_return_if_fail (user_data != NULL);
1470 rf_helper = (ReplyForwardHelper *) user_data;
1472 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1473 rf_helper->account_name);
1474 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(),
1475 rf_helper->account_name,
1478 /* Create reply mail */
1479 switch (rf_helper->action) {
1482 modest_tny_msg_create_reply_msg (msg, header, from,
1483 (use_signature) ? signature : NULL,
1484 rf_helper->reply_forward_type,
1485 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1487 case ACTION_REPLY_TO_ALL:
1489 modest_tny_msg_create_reply_msg (msg, header, from,
1490 (use_signature) ? signature : NULL,
1491 rf_helper->reply_forward_type,
1492 MODEST_TNY_MSG_REPLY_MODE_ALL);
1493 edit_type = MODEST_EDIT_TYPE_REPLY;
1495 case ACTION_FORWARD:
1497 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1498 rf_helper->reply_forward_type);
1499 edit_type = MODEST_EDIT_TYPE_FORWARD;
1502 g_return_if_reached ();
1509 g_printerr ("modest: failed to create message\n");
1513 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1514 rf_helper->account_name,
1515 TNY_ACCOUNT_TYPE_STORE);
1517 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1521 /* Create and register the windows */
1522 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1523 mgr = modest_runtime_get_window_mgr ();
1524 modest_window_mgr_register_window (mgr, msg_win);
1526 if (rf_helper->parent_window != NULL) {
1527 gdouble parent_zoom;
1529 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1530 modest_window_set_zoom (msg_win, parent_zoom);
1533 /* Show edit window */
1534 gtk_widget_show_all (GTK_WIDGET (msg_win));
1538 g_object_unref (msg_win);
1540 g_object_unref (G_OBJECT (new_msg));
1542 g_object_unref (G_OBJECT (account));
1543 /* g_object_unref (msg); */
1544 free_reply_forward_helper (rf_helper);
1547 /* Checks a list of headers. If any of them are not currently
1548 * downloaded (CACHED) then returns TRUE else returns FALSE.
1551 header_list_count_uncached_msgs (TnyList *header_list)
1554 gint uncached_messages = 0;
1556 iter = tny_list_create_iterator (header_list);
1557 while (!tny_iterator_is_done (iter)) {
1560 header = TNY_HEADER (tny_iterator_get_current (iter));
1562 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1563 uncached_messages ++;
1564 g_object_unref (header);
1567 tny_iterator_next (iter);
1569 g_object_unref (iter);
1571 return uncached_messages;
1574 /* Returns FALSE if the user does not want to download the
1575 * messages. Returns TRUE if the user allowed the download.
1578 connect_to_get_msg (ModestWindow *win,
1579 gint num_of_uncached_msgs,
1580 TnyAccount *account)
1582 GtkResponseType response;
1584 /* Allways download if we are online. */
1585 if (tny_device_is_online (modest_runtime_get_device ()))
1588 /* If offline, then ask for user permission to download the messages */
1589 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1590 ngettext("mcen_nc_get_msg",
1592 num_of_uncached_msgs));
1594 if (response == GTK_RESPONSE_CANCEL)
1597 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1601 * Common code for the reply and forward actions
1604 reply_forward (ReplyForwardAction action, ModestWindow *win)
1606 ModestMailOperation *mail_op = NULL;
1607 TnyList *header_list = NULL;
1608 ReplyForwardHelper *rf_helper = NULL;
1609 guint reply_forward_type;
1610 gboolean continue_download = TRUE;
1611 gboolean do_retrieve = TRUE;
1613 g_return_if_fail (MODEST_IS_WINDOW(win));
1616 /* we check for low-mem; in that case, show a warning, and don't allow
1617 * reply/forward (because it could potentially require a lot of memory */
1618 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1622 /* we need an account when editing */
1623 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1624 if (!modest_ui_actions_run_account_setup_wizard (win))
1628 header_list = get_selected_headers (win);
1632 reply_forward_type =
1633 modest_conf_get_int (modest_runtime_get_conf (),
1634 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1637 /* check if we need to download msg before asking about it */
1638 do_retrieve = (action == ACTION_FORWARD) ||
1639 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1642 gint num_of_unc_msgs;
1644 /* check that the messages have been previously downloaded */
1645 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1646 /* If there are any uncached message ask the user
1647 * whether he/she wants to download them. */
1648 if (num_of_unc_msgs) {
1649 TnyAccount *account = get_account_from_header_list (header_list);
1651 continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1652 g_object_unref (account);
1657 if (!continue_download) {
1658 g_object_unref (header_list);
1662 /* We assume that we can only select messages of the
1663 same folder and that we reply all of them from the
1664 same account. In fact the interface currently only
1665 allows single selection */
1668 rf_helper = g_slice_new0 (ReplyForwardHelper);
1669 rf_helper->reply_forward_type = reply_forward_type;
1670 rf_helper->action = action;
1671 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1673 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1674 rf_helper->parent_window = GTK_WIDGET (win);
1675 if (!rf_helper->account_name)
1676 rf_helper->account_name =
1677 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1679 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1682 /* Get header and message. Do not free them here, the
1683 reply_forward_cb must do it */
1684 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1685 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1686 if (!msg || !header) {
1688 g_object_unref (msg);
1689 g_printerr ("modest: no message found\n");
1692 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1695 g_object_unref (header);
1700 /* Only reply/forward to one message */
1701 iter = tny_list_create_iterator (header_list);
1702 header = TNY_HEADER (tny_iterator_get_current (iter));
1703 g_object_unref (iter);
1706 /* Retrieve messages */
1709 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1710 modest_ui_actions_disk_operations_error_handler,
1712 modest_mail_operation_queue_add (
1713 modest_runtime_get_mail_operation_queue (), mail_op);
1715 modest_mail_operation_get_msg (mail_op,
1721 g_object_unref(mail_op);
1723 /* we put a ref here to prevent double unref as the reply
1724 * forward callback unrefs the header at its end */
1725 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1729 g_object_unref (header);
1735 g_object_unref (header_list);
1739 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1741 g_return_if_fail (MODEST_IS_WINDOW(win));
1743 reply_forward (ACTION_REPLY, win);
1747 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1749 g_return_if_fail (MODEST_IS_WINDOW(win));
1751 reply_forward (ACTION_FORWARD, win);
1755 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1757 g_return_if_fail (MODEST_IS_WINDOW(win));
1759 reply_forward (ACTION_REPLY_TO_ALL, win);
1763 modest_ui_actions_on_next (GtkAction *action,
1764 ModestWindow *window)
1766 if (MODEST_IS_MAIN_WINDOW (window)) {
1767 GtkWidget *header_view;
1769 header_view = modest_main_window_get_child_widget (
1770 MODEST_MAIN_WINDOW(window),
1771 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1775 modest_header_view_select_next (
1776 MODEST_HEADER_VIEW(header_view));
1777 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1778 modest_msg_view_window_select_next_message (
1779 MODEST_MSG_VIEW_WINDOW (window));
1781 g_return_if_reached ();
1786 modest_ui_actions_on_prev (GtkAction *action,
1787 ModestWindow *window)
1789 g_return_if_fail (MODEST_IS_WINDOW(window));
1791 if (MODEST_IS_MAIN_WINDOW (window)) {
1792 GtkWidget *header_view;
1793 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1794 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1798 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1799 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1800 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1802 g_return_if_reached ();
1807 modest_ui_actions_on_sort (GtkAction *action,
1808 ModestWindow *window)
1810 g_return_if_fail (MODEST_IS_WINDOW(window));
1812 if (MODEST_IS_MAIN_WINDOW (window)) {
1813 GtkWidget *header_view;
1814 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1815 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1817 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1822 /* Show sorting dialog */
1823 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1828 new_messages_arrived (ModestMailOperation *self,
1829 TnyList *new_headers,
1833 gboolean show_visual_notifications;
1835 source = modest_mail_operation_get_source (self);
1836 show_visual_notifications = (source) ? FALSE : TRUE;
1838 g_object_unref (source);
1840 /* Notify new messages have been downloaded. If the
1841 send&receive was invoked by the user then do not show any
1842 visual notification, only play a sound and activate the LED
1843 (for the Maemo version) */
1844 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1845 modest_platform_on_new_headers_received (new_headers,
1846 show_visual_notifications);
1851 retrieve_all_messages_cb (GObject *source,
1853 guint retrieve_limit)
1859 window = GTK_WINDOW (source);
1860 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
1861 num_msgs, retrieve_limit);
1863 /* Ask the user if they want to retrieve all the messages */
1865 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1866 _("mcen_bd_get_all"),
1867 _("mcen_bd_newest_only"));
1868 /* Free and return */
1870 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1874 TnyAccount *account;
1876 gchar *account_name;
1877 gboolean poke_status;
1878 gboolean interactive;
1879 ModestMailOperation *mail_op;
1883 do_send_receive_performer (gboolean canceled,
1885 GtkWindow *parent_window,
1886 TnyAccount *account,
1889 SendReceiveInfo *info;
1891 info = (SendReceiveInfo *) user_data;
1893 if (err || canceled) {
1894 /* In memory full conditions we could get this error here */
1895 if (err && is_memory_full_error (err)) {
1896 modest_platform_information_banner ((GtkWidget *) parent_window,
1897 NULL, dgettext("ke-recv",
1898 "cerm_device_memory_full"));
1900 if (info->mail_op) {
1901 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
1907 /* Set send/receive operation in progress */
1908 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1909 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1912 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1913 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
1914 G_CALLBACK (on_send_receive_finished),
1917 /* Send & receive. */
1918 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
1919 (info->win) ? retrieve_all_messages_cb : NULL,
1920 new_messages_arrived, info->win);
1925 g_object_unref (G_OBJECT (info->mail_op));
1926 if (info->account_name)
1927 g_free (info->account_name);
1929 g_object_unref (info->win);
1931 g_object_unref (info->account);
1932 g_slice_free (SendReceiveInfo, info);
1936 * This function performs the send & receive required actions. The
1937 * window is used to create the mail operation. Typically it should
1938 * always be the main window, but we pass it as argument in order to
1942 modest_ui_actions_do_send_receive (const gchar *account_name,
1943 gboolean force_connection,
1944 gboolean poke_status,
1945 gboolean interactive,
1948 gchar *acc_name = NULL;
1949 SendReceiveInfo *info;
1950 ModestTnyAccountStore *acc_store;
1952 /* If no account name was provided then get the current account, and if
1953 there is no current account then pick the default one: */
1954 if (!account_name) {
1956 acc_name = g_strdup (modest_window_get_active_account (win));
1958 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1960 g_printerr ("modest: cannot get default account\n");
1964 acc_name = g_strdup (account_name);
1967 acc_store = modest_runtime_get_account_store ();
1969 /* Create the info for the connect and perform */
1970 info = g_slice_new (SendReceiveInfo);
1971 info->account_name = acc_name;
1972 info->win = (win) ? g_object_ref (win) : NULL;
1973 info->poke_status = poke_status;
1974 info->interactive = interactive;
1975 info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1976 TNY_ACCOUNT_TYPE_STORE);
1977 /* We need to create the operation here, because otherwise it
1978 could happen that the queue emits the queue-empty signal
1979 while we're trying to connect the account */
1980 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1981 modest_ui_actions_disk_operations_error_handler,
1983 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
1985 /* Invoke the connect and perform */
1986 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
1987 force_connection, info->account,
1988 do_send_receive_performer, info);
1993 modest_ui_actions_do_cancel_send (const gchar *account_name,
1996 TnyTransportAccount *transport_account;
1997 TnySendQueue *send_queue = NULL;
1998 GError *error = NULL;
2000 /* Get transport account */
2002 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2003 (modest_runtime_get_account_store(),
2005 TNY_ACCOUNT_TYPE_TRANSPORT));
2006 if (!transport_account) {
2007 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2012 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2013 if (!TNY_IS_SEND_QUEUE(send_queue)) {
2014 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2015 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2016 "modest: could not find send queue for account\n");
2018 /* Cancel the current send */
2019 tny_account_cancel (TNY_ACCOUNT (transport_account));
2021 /* Suspend all pending messages */
2022 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2026 if (transport_account != NULL)
2027 g_object_unref (G_OBJECT (transport_account));
2031 modest_ui_actions_cancel_send_all (ModestWindow *win)
2033 GSList *account_names, *iter;
2035 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2038 iter = account_names;
2040 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2041 iter = g_slist_next (iter);
2044 modest_account_mgr_free_account_names (account_names);
2045 account_names = NULL;
2049 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2052 /* Check if accounts exist */
2053 gboolean accounts_exist =
2054 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2056 /* If not, allow the user to create an account before trying to send/receive. */
2057 if (!accounts_exist)
2058 modest_ui_actions_on_accounts (NULL, win);
2060 /* Cancel all sending operaitons */
2061 modest_ui_actions_cancel_send_all (win);
2065 * Refreshes all accounts. This function will be used by automatic
2069 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2070 gboolean force_connection,
2071 gboolean poke_status,
2072 gboolean interactive)
2074 GSList *account_names, *iter;
2076 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2079 iter = account_names;
2081 modest_ui_actions_do_send_receive ((const char*) iter->data,
2083 poke_status, interactive, win);
2084 iter = g_slist_next (iter);
2087 modest_account_mgr_free_account_names (account_names);
2088 account_names = NULL;
2092 * Handler of the click on Send&Receive button in the main toolbar
2095 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2097 /* Check if accounts exist */
2098 gboolean accounts_exist;
2101 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2103 /* If not, allow the user to create an account before trying to send/receive. */
2104 if (!accounts_exist)
2105 modest_ui_actions_on_accounts (NULL, win);
2107 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2108 if (MODEST_IS_MAIN_WINDOW (win)) {
2109 GtkWidget *folder_view;
2110 TnyFolderStore *folder_store;
2113 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2114 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2118 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2121 g_object_unref (folder_store);
2124 /* Refresh the active account. Force the connection if needed
2125 and poke the status of all folders */
2126 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2131 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2134 GtkWidget *header_view;
2136 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2138 header_view = modest_main_window_get_child_widget (main_window,
2139 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2143 conf = modest_runtime_get_conf ();
2145 /* what is saved/restored is depending on the style; thus; we save with
2146 * old style, then update the style, and restore for this new style
2148 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2150 if (modest_header_view_get_style
2151 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2152 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2153 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2155 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2156 MODEST_HEADER_VIEW_STYLE_DETAILS);
2158 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2159 MODEST_CONF_HEADER_VIEW_KEY);
2164 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2166 ModestMainWindow *main_window)
2168 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2169 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2171 /* in the case the folder is empty, show the empty folder message and focus
2173 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2174 if (modest_header_view_is_empty (header_view)) {
2175 TnyFolder *folder = modest_header_view_get_folder (header_view);
2176 GtkWidget *folder_view =
2177 modest_main_window_get_child_widget (main_window,
2178 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2180 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2181 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2185 /* If no header has been selected then exit */
2190 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2191 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2193 /* Update toolbar dimming state */
2194 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2195 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2199 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2201 ModestMainWindow *main_window)
2204 GtkWidget *open_widget;
2206 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2211 if (modest_header_view_count_selected_headers (header_view) > 1) {
2212 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2216 /* we check for low-mem; in that case, show a warning, and don't allow
2217 * activating headers
2219 if (modest_platform_check_memory_low (MODEST_WINDOW(main_window)))
2222 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2223 open_widget = modest_window_get_action_widget (MODEST_WINDOW (main_window), "/MenuBar/EmailMenu/EmailOpenMenu");
2224 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2227 /* headers = tny_simple_list_new (); */
2228 /* tny_list_prepend (headers, G_OBJECT (header)); */
2229 headers = modest_header_view_get_selected_headers (header_view);
2231 open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2233 g_object_unref (headers);
2237 set_active_account_from_tny_account (TnyAccount *account,
2238 ModestWindow *window)
2240 const gchar *server_acc_name = tny_account_get_id (account);
2242 /* We need the TnyAccount provided by the
2243 account store because that is the one that
2244 knows the name of the Modest account */
2245 TnyAccount *modest_server_account = modest_server_account =
2246 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2247 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2249 if (!modest_server_account) {
2250 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2254 /* Update active account, but only if it's not a pseudo-account */
2255 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2256 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2257 const gchar *modest_acc_name =
2258 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2259 if (modest_acc_name)
2260 modest_window_set_active_account (window, modest_acc_name);
2263 g_object_unref (modest_server_account);
2268 folder_refreshed_cb (ModestMailOperation *mail_op,
2272 ModestMainWindow *win = NULL;
2273 GtkWidget *header_view;
2275 g_return_if_fail (TNY_IS_FOLDER (folder));
2277 win = MODEST_MAIN_WINDOW (user_data);
2279 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2282 TnyFolder *current_folder;
2284 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2285 if (current_folder != NULL && folder != current_folder) {
2286 g_object_unref (current_folder);
2288 } else if (current_folder)
2289 g_object_unref (current_folder);
2292 /* Check if folder is empty and set headers view contents style */
2293 if (tny_folder_get_all_count (folder) == 0)
2294 modest_main_window_set_contents_style (win,
2295 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2300 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2301 TnyFolderStore *folder_store,
2303 ModestMainWindow *main_window)
2306 GtkWidget *header_view;
2308 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2310 header_view = modest_main_window_get_child_widget(main_window,
2311 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2315 conf = modest_runtime_get_conf ();
2317 if (TNY_IS_ACCOUNT (folder_store)) {
2319 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2321 /* Show account details */
2322 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2325 if (TNY_IS_FOLDER (folder_store) && selected) {
2327 /* Update the active account */
2328 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2330 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2331 g_object_unref (account);
2335 /* Set the header style by default, it could
2336 be changed later by the refresh callback to
2338 modest_main_window_set_contents_style (main_window,
2339 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2341 /* Set folder on header view. This function
2342 will call tny_folder_refresh_async so we
2343 pass a callback that will be called when
2344 finished. We use that callback to set the
2345 empty view if there are no messages */
2346 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2347 TNY_FOLDER (folder_store),
2348 folder_refreshed_cb,
2351 /* Restore configuration. We need to do this
2352 *after* the set_folder because the widget
2353 memory asks the header view about its
2355 modest_widget_memory_restore (modest_runtime_get_conf (),
2356 G_OBJECT(header_view),
2357 MODEST_CONF_HEADER_VIEW_KEY);
2359 /* No need to save the header view
2360 configuration for Maemo because it only
2361 saves the sorting stuff and that it's
2362 already being done by the sort
2363 dialog. Remove it when the GNOME version
2364 has the same behaviour */
2365 #ifdef MODEST_PLATFORM_GNOME
2366 if (modest_main_window_get_contents_style (main_window) ==
2367 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2368 modest_widget_memory_save (conf, G_OBJECT (header_view),
2369 MODEST_CONF_HEADER_VIEW_KEY);
2371 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2375 /* Update dimming state */
2376 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2377 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2381 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2388 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2390 online = tny_device_is_online (modest_runtime_get_device());
2393 /* already online -- the item is simply not there... */
2394 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2396 GTK_MESSAGE_WARNING,
2398 _("The %s you selected cannot be found"),
2400 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2401 gtk_dialog_run (GTK_DIALOG(dialog));
2403 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2406 _("mcen_bd_dialog_cancel"),
2407 GTK_RESPONSE_REJECT,
2408 _("mcen_bd_dialog_ok"),
2409 GTK_RESPONSE_ACCEPT,
2411 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2412 "Do you want to get online?"), item);
2413 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2414 gtk_label_new (txt), FALSE, FALSE, 0);
2415 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2418 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2419 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2420 /* TODO: Comment about why is this commented out: */
2421 /* modest_platform_connect_and_wait (); */
2424 gtk_widget_destroy (dialog);
2428 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2431 /* g_message ("%s %s", __FUNCTION__, link); */
2436 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2439 modest_platform_activate_uri (link);
2443 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2446 modest_platform_show_uri_popup (link);
2450 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2453 /* we check for low-mem; in that case, show a warning, and don't allow
2454 * viewing attachments
2456 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
2459 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2463 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2464 const gchar *address,
2467 /* g_message ("%s %s", __FUNCTION__, address); */
2471 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2472 TnyMsg *saved_draft,
2475 ModestMsgEditWindow *edit_window;
2476 ModestMainWindow *win;
2478 /* FIXME. Make the header view sensitive again. This is a
2479 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2481 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2482 modest_runtime_get_window_mgr(), FALSE));
2484 GtkWidget *hdrview = modest_main_window_get_child_widget(
2485 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2486 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2489 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2491 /* Set draft is there was no error */
2492 if (!modest_mail_operation_get_error (mail_op))
2493 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2495 g_object_unref(edit_window);
2499 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2501 TnyTransportAccount *transport_account;
2502 ModestMailOperation *mail_operation;
2504 gchar *account_name, *from;
2505 ModestAccountMgr *account_mgr;
2506 /* char *info_text; */
2507 gboolean had_error = FALSE;
2508 guint64 available_disk, expected_size;
2511 ModestMainWindow *win;
2513 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2515 data = modest_msg_edit_window_get_msg_data (edit_window);
2518 available_disk = modest_folder_available_space (NULL);
2519 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2520 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2525 if ((available_disk != -1) && expected_size > available_disk) {
2526 modest_msg_edit_window_free_msg_data (edit_window, data);
2528 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2533 * djcb: if we're in low-memory state, we only allow for
2534 * saving messages smaller than
2535 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2536 * should still allow for sending anything critical...
2538 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2540 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2541 modest_msg_edit_window_free_msg_data (edit_window, data);
2547 * djcb: we also make sure that the attachments are smaller than the max size
2548 * this is for the case where we'd try to forward a message with attachments
2549 * bigger than our max allowed size, or sending an message from drafts which
2550 * somehow got past our checks when attaching.
2552 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2553 modest_platform_run_information_dialog (
2554 GTK_WINDOW(edit_window),
2555 dgettext("ke-recv","memr_ib_operation_disabled"),
2557 modest_msg_edit_window_free_msg_data (edit_window, data);
2561 account_name = g_strdup (data->account_name);
2562 account_mgr = modest_runtime_get_account_mgr();
2564 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2566 account_name = modest_account_mgr_get_default_account (account_mgr);
2567 if (!account_name) {
2568 g_printerr ("modest: no account found\n");
2569 modest_msg_edit_window_free_msg_data (edit_window, data);
2573 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2574 account_name = g_strdup (data->account_name);
2578 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2579 (modest_runtime_get_account_store(),
2581 TNY_ACCOUNT_TYPE_TRANSPORT));
2582 if (!transport_account) {
2583 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2584 g_free (account_name);
2585 modest_msg_edit_window_free_msg_data (edit_window, data);
2588 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2590 /* Create the mail operation */
2591 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2593 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2595 modest_mail_operation_save_to_drafts (mail_operation,
2607 data->priority_flags,
2608 on_save_to_drafts_cb,
2609 g_object_ref(edit_window));
2611 /* Use the main window as the parent of the banner, if the
2612 main window does not exist it won't be shown, if the parent
2613 window exists then it's properly shown. We don't use the
2614 editor window because it could be closed (save to drafts
2615 could happen after closing the window */
2616 win = (ModestMainWindow *)
2617 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2619 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2620 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2623 modest_msg_edit_window_set_modified (edit_window, FALSE);
2627 g_free (account_name);
2628 g_object_unref (G_OBJECT (transport_account));
2629 g_object_unref (G_OBJECT (mail_operation));
2631 modest_msg_edit_window_free_msg_data (edit_window, data);
2634 * If the drafts folder is selected then make the header view
2635 * insensitive while the message is being saved to drafts
2636 * (it'll be sensitive again in on_save_to_drafts_cb()). This
2637 * is not very clean but it avoids letting the drafts folder
2638 * in an inconsistent state: the user could edit the message
2639 * being saved and undesirable things would happen.
2640 * In the average case the user won't notice anything at
2641 * all. In the worst case (the user is editing a really big
2642 * file from Drafts) the header view will be insensitive
2643 * during the saving process (10 or 20 seconds, depending on
2644 * the message). Anyway this is just a quick workaround: once
2645 * we find a better solution it should be removed
2646 * See NB#65125 (commend #18) for details.
2648 if (!had_error && win != NULL) {
2649 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2650 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2652 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2654 if (modest_tny_folder_is_local_folder(folder)) {
2655 TnyFolderType folder_type;
2656 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2657 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2658 GtkWidget *hdrview = modest_main_window_get_child_widget(
2659 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2660 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2664 if (folder != NULL) g_object_unref(folder);
2671 /* For instance, when clicking the Send toolbar button when editing a message: */
2673 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2675 TnyTransportAccount *transport_account = NULL;
2676 gboolean had_error = FALSE;
2677 guint64 available_disk, expected_size;
2681 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2683 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2686 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2689 available_disk = modest_folder_available_space (NULL);
2690 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2691 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2696 if ((available_disk != -1) && expected_size > available_disk) {
2697 modest_msg_edit_window_free_msg_data (edit_window, data);
2699 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2705 * djcb: if we're in low-memory state, we only allow for sending messages
2706 * smaller than MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h)
2707 * this should still allow for sending anything critical...
2709 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2710 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2711 modest_msg_edit_window_free_msg_data (edit_window, data);
2717 * djcb: we also make sure that the attachments are smaller than the max size
2718 * this is for the case where we'd try to forward a message with attachments
2719 * bigger than our max allowed size, or sending an message from drafts which
2720 * somehow got past our checks when attaching.
2722 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2723 modest_platform_run_information_dialog (
2724 GTK_WINDOW(edit_window),
2725 dgettext("ke-recv","memr_ib_operation_disabled"),
2727 modest_msg_edit_window_free_msg_data (edit_window, data);
2731 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2732 gchar *account_name = g_strdup (data->account_name);
2734 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2737 account_name = modest_account_mgr_get_default_account (account_mgr);
2739 if (!account_name) {
2740 modest_msg_edit_window_free_msg_data (edit_window, data);
2741 /* Run account setup wizard */
2742 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2747 /* Get the currently-active transport account for this modest account: */
2748 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2749 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2750 (modest_runtime_get_account_store(),
2751 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2754 if (!transport_account) {
2755 modest_msg_edit_window_free_msg_data (edit_window, data);
2756 /* Run account setup wizard */
2757 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2761 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2763 /* Create the mail operation */
2764 ModestMailOperation *mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
2765 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2767 modest_mail_operation_send_new_mail (mail_operation,
2779 data->priority_flags);
2781 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2782 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2785 if (modest_mail_operation_get_error (mail_operation) != NULL) {
2786 const GError *error = modest_mail_operation_get_error (mail_operation);
2787 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2788 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2789 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2796 g_free (account_name);
2797 g_object_unref (G_OBJECT (transport_account));
2798 g_object_unref (G_OBJECT (mail_operation));
2800 modest_msg_edit_window_free_msg_data (edit_window, data);
2803 modest_msg_edit_window_set_sent (edit_window, TRUE);
2805 /* Save settings and close the window: */
2806 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2813 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2814 ModestMsgEditWindow *window)
2816 ModestMsgEditFormatState *format_state = NULL;
2818 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2819 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2821 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2824 format_state = modest_msg_edit_window_get_format_state (window);
2825 g_return_if_fail (format_state != NULL);
2827 format_state->bold = gtk_toggle_action_get_active (action);
2828 modest_msg_edit_window_set_format_state (window, format_state);
2829 g_free (format_state);
2834 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2835 ModestMsgEditWindow *window)
2837 ModestMsgEditFormatState *format_state = NULL;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2842 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2845 format_state = modest_msg_edit_window_get_format_state (window);
2846 g_return_if_fail (format_state != NULL);
2848 format_state->italics = gtk_toggle_action_get_active (action);
2849 modest_msg_edit_window_set_format_state (window, format_state);
2850 g_free (format_state);
2855 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2856 ModestMsgEditWindow *window)
2858 ModestMsgEditFormatState *format_state = NULL;
2860 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2861 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2863 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2866 format_state = modest_msg_edit_window_get_format_state (window);
2867 g_return_if_fail (format_state != NULL);
2869 format_state->bullet = gtk_toggle_action_get_active (action);
2870 modest_msg_edit_window_set_format_state (window, format_state);
2871 g_free (format_state);
2876 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2877 GtkRadioAction *selected,
2878 ModestMsgEditWindow *window)
2880 ModestMsgEditFormatState *format_state = NULL;
2881 GtkJustification value;
2883 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2885 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2888 value = gtk_radio_action_get_current_value (selected);
2890 format_state = modest_msg_edit_window_get_format_state (window);
2891 g_return_if_fail (format_state != NULL);
2893 format_state->justification = value;
2894 modest_msg_edit_window_set_format_state (window, format_state);
2895 g_free (format_state);
2899 modest_ui_actions_on_select_editor_color (GtkAction *action,
2900 ModestMsgEditWindow *window)
2902 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2903 g_return_if_fail (GTK_IS_ACTION (action));
2905 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2908 modest_msg_edit_window_select_color (window);
2912 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2913 ModestMsgEditWindow *window)
2915 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2916 g_return_if_fail (GTK_IS_ACTION (action));
2918 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2921 modest_msg_edit_window_select_background_color (window);
2925 modest_ui_actions_on_insert_image (GtkAction *action,
2926 ModestMsgEditWindow *window)
2928 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2929 g_return_if_fail (GTK_IS_ACTION (action));
2932 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2935 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2938 modest_msg_edit_window_insert_image (window);
2942 modest_ui_actions_on_attach_file (GtkAction *action,
2943 ModestMsgEditWindow *window)
2945 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2946 g_return_if_fail (GTK_IS_ACTION (action));
2948 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2951 modest_msg_edit_window_offer_attach_file (window);
2955 modest_ui_actions_on_remove_attachments (GtkAction *action,
2956 ModestMsgEditWindow *window)
2958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2959 g_return_if_fail (GTK_IS_ACTION (action));
2961 modest_msg_edit_window_remove_attachments (window, NULL);
2965 do_create_folder_cb (ModestMailOperation *mail_op,
2966 TnyFolderStore *parent_folder,
2967 TnyFolder *new_folder,
2970 gchar *suggested_name = (gchar *) user_data;
2971 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2973 if (modest_mail_operation_get_error (mail_op)) {
2975 /* Show an error. If there was some problem writing to
2976 disk, show it, otherwise show the generic folder
2977 create error. We do it here and not in an error
2978 handler because the call to do_create_folder will
2979 stop the main loop in a gtk_dialog_run and then,
2980 the message won't be shown until that dialog is
2982 modest_ui_actions_disk_operations_error_handler (mail_op,
2983 _("mail_in_ui_folder_create_error"));
2985 /* Try again. Do *NOT* show any error because the mail
2986 operations system will do it for us because we
2987 created the mail_op with new_with_error_handler */
2988 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2990 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2991 * FIXME: any other? */
2992 GtkWidget *folder_view;
2994 if (MODEST_IS_MAIN_WINDOW(source_win))
2996 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2997 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3000 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
3002 /* Select the newly created folder. It could happen
3003 that the widget is no longer there (i.e. the window
3004 has been destroyed, so we need to check this */
3006 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3008 g_object_unref (new_folder);
3010 /* Free. Note that the first time it'll be NULL so noop */
3011 g_free (suggested_name);
3012 g_object_unref (source_win);
3016 do_create_folder (GtkWindow *parent_window,
3017 TnyFolderStore *parent_folder,
3018 const gchar *suggested_name)
3021 gchar *folder_name = NULL;
3023 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3025 (gchar *) suggested_name,
3028 if (result == GTK_RESPONSE_ACCEPT) {
3029 ModestMailOperation *mail_op;
3031 mail_op = modest_mail_operation_new ((GObject *) parent_window);
3032 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3034 modest_mail_operation_create_folder (mail_op,
3036 (const gchar *) folder_name,
3037 do_create_folder_cb,
3039 g_object_unref (mail_op);
3044 create_folder_performer (gboolean canceled,
3046 GtkWindow *parent_window,
3047 TnyAccount *account,
3050 TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3052 if (canceled || err) {
3053 /* In memory full conditions we could get this error here */
3054 if (err && is_memory_full_error (err)) {
3055 modest_platform_information_banner ((GtkWidget *) parent_window,
3056 NULL, dgettext("ke-recv",
3057 "cerm_device_memory_full"));
3062 /* Run the new folder dialog */
3063 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3066 g_object_unref (parent_folder);
3070 modest_ui_actions_create_folder(GtkWidget *parent_window,
3071 GtkWidget *folder_view)
3073 TnyFolderStore *parent_folder;
3075 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3077 if (parent_folder) {
3078 /* The parent folder will be freed in the callback */
3079 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3082 create_folder_performer,
3088 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3090 GtkWidget *folder_view;
3092 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3094 folder_view = modest_main_window_get_child_widget (main_window,
3095 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3099 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3103 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3106 const GError *error = NULL;
3107 const gchar *message = NULL;
3109 /* Get error message */
3110 error = modest_mail_operation_get_error (mail_op);
3112 g_return_if_reached ();
3114 switch (error->code) {
3115 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
3116 message = _CS("ckdg_ib_folder_already_exists");
3119 message = _("emev_ib_ui_imap_unable_to_rename");
3122 /* We don't set a parent for the dialog because the dialog
3123 will be destroyed so the banner won't appear */
3124 modest_platform_information_banner (NULL, NULL, message);
3128 TnyFolderStore *folder;
3133 on_rename_folder_cb (ModestMailOperation *mail_op,
3134 TnyFolder *new_folder,
3137 ModestFolderView *folder_view;
3139 /* If the window was closed when renaming a folder this could
3141 if (!MODEST_IS_FOLDER_VIEW (user_data))
3144 folder_view = MODEST_FOLDER_VIEW (user_data);
3145 /* Note that if the rename fails new_folder will be NULL */
3147 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3149 modest_folder_view_select_first_inbox_or_local (folder_view);
3151 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3155 on_rename_folder_performer (gboolean canceled,
3157 GtkWindow *parent_window,
3158 TnyAccount *account,
3161 ModestMailOperation *mail_op = NULL;
3162 GtkTreeSelection *sel = NULL;
3163 GtkWidget *folder_view = NULL;
3164 RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3166 if (canceled || err) {
3167 /* In memory full conditions we could get this error here */
3168 if (err && is_memory_full_error (err)) {
3169 modest_platform_information_banner ((GtkWidget *) parent_window,
3170 NULL, dgettext("ke-recv",
3171 "cerm_device_memory_full"));
3173 } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3175 folder_view = modest_main_window_get_child_widget (
3176 MODEST_MAIN_WINDOW (parent_window),
3177 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3180 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3181 modest_ui_actions_rename_folder_error_handler,
3182 parent_window, NULL);
3184 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3187 /* Clear the headers view */
3188 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3189 gtk_tree_selection_unselect_all (sel);
3191 /* Actually rename the folder */
3192 modest_mail_operation_rename_folder (mail_op,
3193 TNY_FOLDER (data->folder),
3194 (const gchar *) (data->new_name),
3195 on_rename_folder_cb,
3197 g_object_unref (mail_op);
3200 g_free (data->new_name);
3205 modest_ui_actions_on_rename_folder (GtkAction *action,
3206 ModestMainWindow *main_window)
3208 TnyFolderStore *folder;
3209 GtkWidget *folder_view;
3210 GtkWidget *header_view;
3212 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3214 folder_view = modest_main_window_get_child_widget (main_window,
3215 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3219 header_view = modest_main_window_get_child_widget (main_window,
3220 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3225 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3230 if (TNY_IS_FOLDER (folder)) {
3233 const gchar *current_name;
3234 TnyFolderStore *parent;
3235 gboolean do_rename = TRUE;
3237 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3238 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3239 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
3240 parent, current_name,
3242 g_object_unref (parent);
3244 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3247 RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3248 rename_folder_data->folder = folder;
3249 rename_folder_data->new_name = folder_name;
3250 modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3251 folder, on_rename_folder_performer, rename_folder_data);
3254 g_object_unref (folder);
3258 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3261 GObject *win = modest_mail_operation_get_source (mail_op);
3263 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3264 _("mail_in_ui_folder_delete_error"),
3266 g_object_unref (win);
3270 TnyFolderStore *folder;
3271 gboolean move_to_trash;
3275 on_delete_folder_cb (gboolean canceled,
3277 GtkWindow *parent_window,
3278 TnyAccount *account,
3281 DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3282 GtkWidget *folder_view;
3283 ModestMailOperation *mail_op;
3284 GtkTreeSelection *sel;
3286 if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3287 g_object_unref (G_OBJECT (info->folder));
3292 folder_view = modest_main_window_get_child_widget (
3293 MODEST_MAIN_WINDOW (parent_window),
3294 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3296 /* Unselect the folder before deleting it to free the headers */
3297 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3298 gtk_tree_selection_unselect_all (sel);
3300 /* Create the mail operation */
3302 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3303 modest_ui_actions_delete_folder_error_handler,
3306 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3308 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3310 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3312 g_object_unref (G_OBJECT (mail_op));
3313 g_object_unref (G_OBJECT (info->folder));
3318 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3320 TnyFolderStore *folder;
3321 GtkWidget *folder_view;
3325 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3327 folder_view = modest_main_window_get_child_widget (main_window,
3328 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3332 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3334 /* Show an error if it's an account */
3335 if (!TNY_IS_FOLDER (folder)) {
3336 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3337 _("mail_in_ui_folder_delete_error"),
3339 g_object_unref (G_OBJECT (folder));
3344 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
3345 tny_folder_get_name (TNY_FOLDER (folder)));
3346 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3347 (const gchar *) message);
3350 if (response == GTK_RESPONSE_OK) {
3351 DeleteFolderInfo *info;
3352 info = g_new0(DeleteFolderInfo, 1);
3353 info->folder = folder;
3354 info->move_to_trash = move_to_trash;
3355 g_object_ref (G_OBJECT (info->folder));
3356 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3357 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window),
3359 TNY_FOLDER_STORE (account),
3360 on_delete_folder_cb, info);
3361 g_object_unref (account);
3363 g_object_unref (G_OBJECT (folder));
3367 modest_ui_actions_on_delete_folder (GtkAction *action,
3368 ModestMainWindow *main_window)
3370 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3372 delete_folder (main_window, FALSE);
3376 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3378 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3380 delete_folder (main_window, TRUE);
3384 typedef struct _PasswordDialogFields {
3385 GtkWidget *username;
3386 GtkWidget *password;
3388 } PasswordDialogFields;
3391 password_dialog_check_field (GtkEditable *editable,
3392 PasswordDialogFields *fields)
3395 gboolean any_value_empty = FALSE;
3397 value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3398 if ((value == NULL) || value[0] == '\0') {
3399 any_value_empty = TRUE;
3401 value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3402 if ((value == NULL) || value[0] == '\0') {
3403 any_value_empty = TRUE;
3405 gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3409 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3410 const gchar* server_account_name,
3415 ModestMainWindow *main_window)
3417 g_return_if_fail(server_account_name);
3418 gboolean completed = FALSE;
3419 PasswordDialogFields *fields = NULL;
3421 /* Initalize output parameters: */
3428 #ifdef MODEST_PLATFORM_MAEMO
3429 /* Maemo uses a different (awkward) button order,
3430 * It should probably just use gtk_alternative_dialog_button_order ().
3432 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3435 _("mcen_bd_dialog_ok"),
3436 GTK_RESPONSE_ACCEPT,
3437 _("mcen_bd_dialog_cancel"),
3438 GTK_RESPONSE_REJECT,
3441 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3445 GTK_RESPONSE_REJECT,
3447 GTK_RESPONSE_ACCEPT,
3449 #endif /* MODEST_PLATFORM_MAEMO */
3451 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3453 gchar *server_name = modest_account_mgr_get_server_account_hostname (
3454 modest_runtime_get_account_mgr(), server_account_name);
3455 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3456 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3462 /* This causes a warning because the logical ID has no %s in it,
3463 * though the translation does, but there is not much we can do about that: */
3464 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3465 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3468 g_free (server_name);
3472 gchar *initial_username = modest_account_mgr_get_server_account_username (
3473 modest_runtime_get_account_mgr(), server_account_name);
3475 GtkWidget *entry_username = gtk_entry_new ();
3476 if (initial_username)
3477 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3478 /* Dim this if a connection has ever succeeded with this username,
3479 * as per the UI spec: */
3480 /* const gboolean username_known = */
3481 /* modest_account_mgr_get_server_account_username_has_succeeded( */
3482 /* modest_runtime_get_account_mgr(), server_account_name); */
3483 /* gtk_widget_set_sensitive (entry_username, !username_known); */
3485 /* We drop the username sensitive code and disallow changing it here
3486 * as tinymail does not support really changing the username in the callback
3488 gtk_widget_set_sensitive (entry_username, FALSE);
3490 #ifdef MODEST_PLATFORM_MAEMO
3491 /* Auto-capitalization is the default, so let's turn it off: */
3492 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3494 /* Create a size group to be used by all captions.
3495 * Note that HildonCaption does not create a default size group if we do not specify one.
3496 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3497 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3499 GtkWidget *caption = hildon_caption_new (sizegroup,
3500 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3501 gtk_widget_show (entry_username);
3502 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3503 FALSE, FALSE, MODEST_MARGIN_HALF);
3504 gtk_widget_show (caption);
3506 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3508 #endif /* MODEST_PLATFORM_MAEMO */
3511 GtkWidget *entry_password = gtk_entry_new ();
3512 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3513 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3515 #ifdef MODEST_PLATFORM_MAEMO
3516 /* Auto-capitalization is the default, so let's turn it off: */
3517 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3518 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3520 caption = hildon_caption_new (sizegroup,
3521 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3522 gtk_widget_show (entry_password);
3523 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3524 FALSE, FALSE, MODEST_MARGIN_HALF);
3525 gtk_widget_show (caption);
3526 g_object_unref (sizegroup);
3528 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3530 #endif /* MODEST_PLATFORM_MAEMO */
3532 if (initial_username != NULL)
3533 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3535 /* This is not in the Maemo UI spec:
3536 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3537 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3541 fields = g_slice_new0 (PasswordDialogFields);
3542 fields->username = entry_username;
3543 fields->password = entry_password;
3544 fields->dialog = dialog;
3546 g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3547 g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3548 password_dialog_check_field (NULL, fields);
3550 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3552 while (!completed) {
3554 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3556 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3558 /* Note that an empty field becomes the "" string */
3559 if (*username && strlen (*username) > 0) {
3560 modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3561 server_account_name,
3565 const gboolean username_was_changed =
3566 (strcmp (*username, initial_username) != 0);
3567 if (username_was_changed) {
3568 g_warning ("%s: tinymail does not yet support changing the "
3569 "username in the get_password() callback.\n", __FUNCTION__);
3573 modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3574 _("mcen_ib_username_pw_incorrect"));
3580 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3582 /* We do not save the password in the configuration,
3583 * because this function is only called for passwords that should
3584 * not be remembered:
3585 modest_server_account_set_password (
3586 modest_runtime_get_account_mgr(), server_account_name,
3593 /* Set parent to NULL or the banner will disappear with its parent dialog */
3594 modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3605 /* This is not in the Maemo UI spec:
3606 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3612 gtk_widget_destroy (dialog);
3613 g_slice_free (PasswordDialogFields, fields);
3615 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3619 modest_ui_actions_on_cut (GtkAction *action,
3620 ModestWindow *window)
3622 GtkWidget *focused_widget;
3623 GtkClipboard *clipboard;
3625 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3626 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3627 if (GTK_IS_EDITABLE (focused_widget)) {
3628 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3629 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3630 gtk_clipboard_store (clipboard);
3631 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3632 GtkTextBuffer *buffer;
3634 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3635 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3636 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3637 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3638 gtk_clipboard_store (clipboard);
3640 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3641 TnyList *header_list = modest_header_view_get_selected_headers (
3642 MODEST_HEADER_VIEW (focused_widget));
3643 gboolean continue_download = FALSE;
3644 gint num_of_unc_msgs;
3646 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3648 if (num_of_unc_msgs) {
3649 TnyAccount *account = get_account_from_header_list (header_list);
3651 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3652 g_object_unref (account);
3656 if (num_of_unc_msgs == 0 || continue_download) {
3657 /* modest_platform_information_banner (
3658 NULL, NULL, _CS("mcen_ib_getting_items"));*/
3659 modest_header_view_cut_selection (
3660 MODEST_HEADER_VIEW (focused_widget));
3663 g_object_unref (header_list);
3664 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3665 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3670 modest_ui_actions_on_copy (GtkAction *action,
3671 ModestWindow *window)
3673 GtkClipboard *clipboard;
3674 GtkWidget *focused_widget;
3675 gboolean copied = TRUE;
3677 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3678 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3680 if (GTK_IS_LABEL (focused_widget)) {
3682 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3683 gtk_clipboard_set_text (clipboard, selection, -1);
3685 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3686 gtk_clipboard_store (clipboard);
3687 } else if (GTK_IS_EDITABLE (focused_widget)) {
3688 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3689 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3690 gtk_clipboard_store (clipboard);
3691 } else if (GTK_IS_HTML (focused_widget)) {
3692 gtk_html_copy (GTK_HTML (focused_widget));
3693 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3694 gtk_clipboard_store (clipboard);
3695 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3696 GtkTextBuffer *buffer;
3697 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3698 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3699 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3700 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3701 gtk_clipboard_store (clipboard);
3703 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3704 TnyList *header_list = modest_header_view_get_selected_headers (
3705 MODEST_HEADER_VIEW (focused_widget));
3706 gboolean continue_download = FALSE;
3707 gint num_of_unc_msgs;
3709 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3711 if (num_of_unc_msgs) {
3712 TnyAccount *account = get_account_from_header_list (header_list);
3714 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3715 g_object_unref (account);
3719 if (num_of_unc_msgs == 0 || continue_download) {
3720 modest_platform_information_banner (
3721 NULL, NULL, _CS("mcen_ib_getting_items"));
3722 modest_header_view_copy_selection (
3723 MODEST_HEADER_VIEW (focused_widget));
3727 g_object_unref (header_list);
3729 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3730 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3733 /* Show information banner if there was a copy to clipboard */
3735 modest_platform_information_banner (
3736 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3740 modest_ui_actions_on_undo (GtkAction *action,
3741 ModestWindow *window)
3743 ModestEmailClipboard *clipboard = NULL;
3745 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3746 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3747 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3748 /* Clear clipboard source */
3749 clipboard = modest_runtime_get_email_clipboard ();
3750 modest_email_clipboard_clear (clipboard);
3753 g_return_if_reached ();
3758 modest_ui_actions_on_redo (GtkAction *action,
3759 ModestWindow *window)
3761 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3762 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3765 g_return_if_reached ();
3771 destroy_information_note (ModestMailOperation *mail_op,
3774 /* destroy information note */
3775 gtk_widget_destroy (GTK_WIDGET(user_data));
3779 destroy_folder_information_note (ModestMailOperation *mail_op,
3780 TnyFolder *new_folder,
3783 /* destroy information note */
3784 gtk_widget_destroy (GTK_WIDGET(user_data));
3789 paste_as_attachment_free (gpointer data)
3791 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3793 if (helper->banner) {
3794 gtk_widget_destroy (helper->banner);
3795 g_object_unref (helper->banner);
3801 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3806 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3807 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3812 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3817 modest_ui_actions_on_paste (GtkAction *action,
3818 ModestWindow *window)
3820 GtkWidget *focused_widget = NULL;
3821 GtkWidget *inf_note = NULL;
3822 ModestMailOperation *mail_op = NULL;
3824 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3825 if (GTK_IS_EDITABLE (focused_widget)) {
3826 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3827 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3828 ModestEmailClipboard *e_clipboard = NULL;
3829 e_clipboard = modest_runtime_get_email_clipboard ();
3830 if (modest_email_clipboard_cleared (e_clipboard)) {
3831 GtkTextBuffer *buffer;
3832 GtkClipboard *clipboard;
3834 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3835 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3836 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3837 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3838 ModestMailOperation *mail_op;
3839 TnyFolder *src_folder;
3842 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3843 helper->window = MODEST_MSG_EDIT_WINDOW (window);
3844 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3845 _CS("ckct_nw_pasting"));
3846 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3847 mail_op = modest_mail_operation_new (G_OBJECT (window));
3848 if (helper->banner != NULL) {
3849 g_object_ref (G_OBJECT (helper->banner));
3850 gtk_widget_show (GTK_WIDGET (helper->banner));
3854 modest_mail_operation_get_msgs_full (mail_op,
3856 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3858 paste_as_attachment_free);
3861 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3862 ModestEmailClipboard *clipboard = NULL;
3863 TnyFolder *src_folder = NULL;
3864 TnyFolderStore *folder_store = NULL;
3865 TnyList *data = NULL;
3866 gboolean delete = FALSE;
3868 /* Check clipboard source */
3869 clipboard = modest_runtime_get_email_clipboard ();
3870 if (modest_email_clipboard_cleared (clipboard))
3873 /* Get elements to paste */
3874 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3876 /* Create a new mail operation */
3877 mail_op = modest_mail_operation_new (G_OBJECT(window));
3879 /* Get destination folder */
3880 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3882 /* transfer messages */
3886 /* Ask for user confirmation */
3888 modest_ui_actions_msgs_move_to_confirmation (window,
3889 TNY_FOLDER (folder_store),
3893 if (response == GTK_RESPONSE_OK) {
3894 /* Launch notification */
3895 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3896 _CS("ckct_nw_pasting"));
3897 if (inf_note != NULL) {
3898 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3899 gtk_widget_show (GTK_WIDGET(inf_note));
3902 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3903 modest_mail_operation_xfer_msgs (mail_op,
3905 TNY_FOLDER (folder_store),
3907 destroy_information_note,
3910 g_object_unref (mail_op);
3913 } else if (src_folder != NULL) {
3914 /* Launch notification */
3915 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3916 _CS("ckct_nw_pasting"));
3917 if (inf_note != NULL) {
3918 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3919 gtk_widget_show (GTK_WIDGET(inf_note));
3922 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3923 modest_mail_operation_xfer_folder (mail_op,
3927 destroy_folder_information_note,
3933 g_object_unref (data);
3934 if (src_folder != NULL)
3935 g_object_unref (src_folder);
3936 if (folder_store != NULL)
3937 g_object_unref (folder_store);
3943 modest_ui_actions_on_select_all (GtkAction *action,
3944 ModestWindow *window)
3946 GtkWidget *focused_widget;
3948 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3949 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3950 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3951 } else if (GTK_IS_LABEL (focused_widget)) {
3952 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3953 } else if (GTK_IS_EDITABLE (focused_widget)) {
3954 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3955 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3956 GtkTextBuffer *buffer;
3957 GtkTextIter start, end;
3959 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3960 gtk_text_buffer_get_start_iter (buffer, &start);
3961 gtk_text_buffer_get_end_iter (buffer, &end);
3962 gtk_text_buffer_select_range (buffer, &start, &end);
3963 } else if (GTK_IS_HTML (focused_widget)) {
3964 gtk_html_select_all (GTK_HTML (focused_widget));
3965 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3966 GtkWidget *header_view = focused_widget;
3967 GtkTreeSelection *selection = NULL;
3969 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3970 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3971 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3974 /* Disable window dimming management */
3975 modest_window_disable_dimming (MODEST_WINDOW(window));
3977 /* Select all messages */
3978 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3979 gtk_tree_selection_select_all (selection);
3981 /* Set focuse on header view */
3982 gtk_widget_grab_focus (header_view);
3985 /* Enable window dimming management */
3986 modest_window_enable_dimming (MODEST_WINDOW(window));
3987 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3993 modest_ui_actions_on_mark_as_read (GtkAction *action,
3994 ModestWindow *window)
3996 g_return_if_fail (MODEST_IS_WINDOW(window));
3998 /* Mark each header as read */
3999 do_headers_action (window, headers_action_mark_as_read, NULL);
4003 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4004 ModestWindow *window)
4006 g_return_if_fail (MODEST_IS_WINDOW(window));
4008 /* Mark each header as read */
4009 do_headers_action (window, headers_action_mark_as_unread, NULL);
4013 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4014 GtkRadioAction *selected,
4015 ModestWindow *window)
4019 value = gtk_radio_action_get_current_value (selected);
4020 if (MODEST_IS_WINDOW (window)) {
4021 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4026 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4027 GtkRadioAction *selected,
4028 ModestWindow *window)
4030 TnyHeaderFlags flags;
4031 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4033 flags = gtk_radio_action_get_current_value (selected);
4034 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4038 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4039 GtkRadioAction *selected,
4040 ModestWindow *window)
4044 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4046 file_format = gtk_radio_action_get_current_value (selected);
4047 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4052 modest_ui_actions_on_zoom_plus (GtkAction *action,
4053 ModestWindow *window)
4055 g_return_if_fail (MODEST_IS_WINDOW (window));
4057 modest_window_zoom_plus (MODEST_WINDOW (window));
4061 modest_ui_actions_on_zoom_minus (GtkAction *action,
4062 ModestWindow *window)
4064 g_return_if_fail (MODEST_IS_WINDOW (window));
4066 modest_window_zoom_minus (MODEST_WINDOW (window));
4070 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
4071 ModestWindow *window)
4073 ModestWindowMgr *mgr;
4074 gboolean fullscreen, active;
4075 g_return_if_fail (MODEST_IS_WINDOW (window));
4077 mgr = modest_runtime_get_window_mgr ();
4079 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4080 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4082 if (active != fullscreen) {
4083 modest_window_mgr_set_fullscreen_mode (mgr, active);
4084 gtk_window_present (GTK_WINDOW (window));
4089 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4090 ModestWindow *window)
4092 ModestWindowMgr *mgr;
4093 gboolean fullscreen;
4095 g_return_if_fail (MODEST_IS_WINDOW (window));
4097 mgr = modest_runtime_get_window_mgr ();
4098 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4099 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4101 gtk_window_present (GTK_WINDOW (window));
4105 * Used by modest_ui_actions_on_details to call do_headers_action
4108 headers_action_show_details (TnyHeader *header,
4109 ModestWindow *window,
4116 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4119 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4120 gtk_widget_show_all (dialog);
4121 gtk_dialog_run (GTK_DIALOG (dialog));
4123 gtk_widget_destroy (dialog);
4127 * Show the folder details in a ModestDetailsDialog widget
4130 show_folder_details (TnyFolder *folder,
4136 dialog = modest_details_dialog_new_with_folder (window, folder);
4139 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4140 gtk_widget_show_all (dialog);
4141 gtk_dialog_run (GTK_DIALOG (dialog));
4143 gtk_widget_destroy (dialog);
4147 * Show the header details in a ModestDetailsDialog widget
4150 modest_ui_actions_on_details (GtkAction *action,
4153 TnyList * headers_list;
4157 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4160 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4163 g_object_unref (msg);
4165 headers_list = get_selected_headers (win);
4169 iter = tny_list_create_iterator (headers_list);
4171 header = TNY_HEADER (tny_iterator_get_current (iter));
4173 headers_action_show_details (header, win, NULL);
4174 g_object_unref (header);
4177 g_object_unref (iter);
4178 g_object_unref (headers_list);
4180 } else if (MODEST_IS_MAIN_WINDOW (win)) {
4181 GtkWidget *folder_view, *header_view;
4183 /* Check which widget has the focus */
4184 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4185 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4186 if (gtk_widget_is_focus (folder_view)) {
4187 TnyFolderStore *folder_store
4188 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4189 if (!folder_store) {
4190 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4193 /* Show only when it's a folder */
4194 /* This function should not be called for account items,
4195 * because we dim the menu item for them. */
4196 if (TNY_IS_FOLDER (folder_store)) {
4197 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4200 g_object_unref (folder_store);
4203 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4204 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4205 /* Show details of each header */
4206 do_headers_action (win, headers_action_show_details, header_view);
4212 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4213 ModestMsgEditWindow *window)
4215 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4217 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4221 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4222 ModestMsgEditWindow *window)
4224 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4226 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4230 modest_ui_actions_toggle_folders_view (GtkAction *action,
4231 ModestMainWindow *main_window)
4233 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4235 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4236 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4238 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4242 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4243 ModestWindow *window)
4245 gboolean active, fullscreen = FALSE;
4246 ModestWindowMgr *mgr;
4248 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4250 /* Check if we want to toggle the toolbar vuew in fullscreen
4252 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4253 "ViewShowToolbarFullScreen")) {
4257 /* Toggle toolbar */
4258 mgr = modest_runtime_get_window_mgr ();
4259 modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4263 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4264 ModestMsgEditWindow *window)
4266 modest_msg_edit_window_select_font (window);
4271 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4272 const gchar *display_name,
4275 /* don't update the display name if it was already set;
4276 * updating the display name apparently is expensive */
4277 const gchar* old_name = gtk_window_get_title (window);
4279 if (display_name == NULL)
4282 if (old_name && display_name && strcmp (old_name, display_name) == 0)
4283 return; /* don't do anything */
4285 /* This is usually used to change the title of the main window, which
4286 * is the one that holds the folder view. Note that this change can
4287 * happen even when the widget doesn't have the focus. */
4288 gtk_window_set_title (window, display_name);
4293 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4295 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4296 modest_msg_edit_window_select_contacts (window);
4300 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4302 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4303 modest_msg_edit_window_check_names (window, FALSE);
4307 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4309 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4310 GTK_WIDGET (user_data));
4314 * This function is used to track changes in the selection of the
4315 * folder view that is inside the "move to" dialog to enable/disable
4316 * the OK button because we do not want the user to select a disallowed
4317 * destination for a folder.
4318 * The user also not desired to be able to use NEW button on items where
4319 * folder creation is not possibel.
4322 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4323 TnyFolderStore *folder_store,
4327 GtkWidget *dialog = NULL;
4328 GtkWidget *ok_button = NULL, *new_button = NULL;
4329 GList *children = NULL;
4330 gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4331 gboolean moving_folder = FALSE;
4332 gboolean is_local_account = TRUE;
4333 GtkWidget *folder_view = NULL;
4334 ModestTnyFolderRules rules;
4336 g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4341 /* Get the OK button */
4342 dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4346 children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4347 ok_button = GTK_WIDGET (children->next->next->data);
4348 new_button = GTK_WIDGET (children->next->data);
4349 g_list_free (children);
4351 /* check if folder_store is an remote account */
4352 if (TNY_IS_ACCOUNT (folder_store)) {
4353 TnyAccount *local_account = NULL;
4354 TnyAccount *mmc_account = NULL;
4355 ModestTnyAccountStore *account_store = NULL;
4357 account_store = modest_runtime_get_account_store ();
4358 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4359 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4361 if ((gpointer) local_account != (gpointer) folder_store &&
4362 (gpointer) mmc_account != (gpointer) folder_store) {
4363 const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4364 ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4365 if (proto_name != NULL) {
4366 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4368 is_local_account = FALSE;
4369 /* New button should be dimmed on remote
4371 new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4373 g_object_unref (local_account);
4374 g_object_unref (mmc_account);
4377 /* Check the target folder rules */
4378 if (TNY_IS_FOLDER (folder_store)) {
4379 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4380 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4381 ok_sensitive = FALSE;
4382 new_sensitive = FALSE;
4387 /* Check if we're moving a folder */
4388 if (MODEST_IS_MAIN_WINDOW (user_data)) {
4389 /* Get the widgets */
4390 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4391 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4392 if (gtk_widget_is_focus (folder_view))
4393 moving_folder = TRUE;
4396 if (moving_folder) {
4397 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4399 /* Get the folder to move */
4400 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4402 /* Check that we're not moving to the same folder */
4403 if (TNY_IS_FOLDER (moved_folder)) {
4404 parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4405 if (parent == folder_store)
4406 ok_sensitive = FALSE;
4407 g_object_unref (parent);
4410 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4411 /* Do not allow to move to an account unless it's the
4412 local folders account */
4413 if (!is_local_account)
4414 ok_sensitive = FALSE;
4417 if (ok_sensitive && (moved_folder == folder_store)) {
4418 /* Do not allow to move to itself */
4419 ok_sensitive = FALSE;
4421 g_object_unref (moved_folder);
4423 TnyFolder *src_folder = NULL;
4425 /* Moving a message */
4426 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4428 TnyHeader *header = NULL;
4429 header = modest_msg_view_window_get_header
4430 (MODEST_MSG_VIEW_WINDOW (user_data));
4431 if (!TNY_IS_HEADER(header))
4432 g_warning ("%s: could not get source header", __FUNCTION__);
4434 src_folder = tny_header_get_folder (header);
4437 g_object_unref (header);
4440 TNY_FOLDER (modest_folder_view_get_selected
4441 (MODEST_FOLDER_VIEW (folder_view)));
4444 if (TNY_IS_FOLDER(src_folder)) {
4445 /* Do not allow to move the msg to the same folder */
4446 /* Do not allow to move the msg to an account */
4447 if ((gpointer) src_folder == (gpointer) folder_store ||
4448 TNY_IS_ACCOUNT (folder_store))
4449 ok_sensitive = FALSE;
4450 g_object_unref (src_folder);
4452 g_warning ("%s: could not get source folder", __FUNCTION__);
4456 /* Set sensitivity of the OK button */
4457 gtk_widget_set_sensitive (ok_button, ok_sensitive);
4458 /* Set sensitivity of the NEW button */
4459 gtk_widget_set_sensitive (new_button, new_sensitive);
4463 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4466 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4468 return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4469 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4473 create_move_to_dialog (GtkWindow *win,
4474 GtkWidget *folder_view,
4475 GtkWidget **tree_view)
4477 GtkWidget *dialog, *scroll;
4478 GtkWidget *new_button;
4480 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4482 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4485 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4486 /* We do this manually so GTK+ does not associate a response ID for
4488 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4489 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4490 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4492 /* Create scrolled window */
4493 scroll = gtk_scrolled_window_new (NULL, NULL);
4494 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
4495 GTK_POLICY_AUTOMATIC,
4496 GTK_POLICY_AUTOMATIC);
4498 /* Create folder view */
4499 *tree_view = modest_platform_create_folder_view (NULL);
4501 /* Track changes in the selection to
4502 * disable the OK button whenever "Move to" is not possible
4503 * disbale NEW button whenever New is not possible */
4504 g_signal_connect (*tree_view,
4505 "folder_selection_changed",
4506 G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4509 /* Listen to clicks on New button */
4510 g_signal_connect (G_OBJECT (new_button),
4512 G_CALLBACK(create_move_to_dialog_on_new_folder),
4515 /* It could happen that we're trying to move a message from a
4516 window (msg window for example) after the main window was
4517 closed, so we can not just get the model of the folder
4519 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4520 const gchar *visible_id = NULL;
4522 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4523 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4524 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4525 MODEST_FOLDER_VIEW(*tree_view));
4528 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4530 /* Show the same account than the one that is shown in the main window */
4531 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
4534 const gchar *active_account_name = NULL;
4535 ModestAccountMgr *mgr = NULL;
4536 ModestAccountSettings *settings = NULL;
4537 ModestServerAccountSettings *store_settings = NULL;
4539 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4540 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4541 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
4542 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4544 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4545 mgr = modest_runtime_get_account_mgr ();
4546 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4549 const gchar *store_account_name;
4550 store_settings = modest_account_settings_get_store_settings (settings);
4551 store_account_name = modest_server_account_settings_get_account_name (store_settings);
4553 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4554 store_account_name);
4555 g_object_unref (store_settings);
4556 g_object_unref (settings);
4560 /* we keep a pointer to the embedded folder view, so we can retrieve it with
4561 * get_folder_view_from_move_to_dialog
4562 * (see above) later (needed for focus handling)
4564 g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4567 /* Hide special folders */
4568 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4570 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4572 /* Add scroll to dialog */
4573 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
4574 scroll, TRUE, TRUE, 0);
4576 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4577 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4585 * Shows a confirmation dialog to the user when we're moving messages
4586 * from a remote server to the local storage. Returns the dialog
4587 * response. If it's other kind of movement then it always returns
4590 * This one is used by the next functions:
4591 * modest_ui_actions_on_paste - commented out
4592 * drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4595 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4596 TnyFolder *dest_folder,
4600 gint response = GTK_RESPONSE_OK;
4601 TnyAccount *account = NULL;
4602 TnyFolder *src_folder = NULL;
4603 TnyIterator *iter = NULL;
4604 TnyHeader *header = NULL;
4606 /* return with OK if the destination is a remote folder */
4607 if (modest_tny_folder_is_remote_folder (dest_folder))
4608 return GTK_RESPONSE_OK;
4610 /* Get source folder */
4611 iter = tny_list_create_iterator (headers);
4612 header = TNY_HEADER (tny_iterator_get_current (iter));
4614 src_folder = tny_header_get_folder (header);
4615 g_object_unref (header);
4617 g_object_unref (iter);
4619 /* if no src_folder, message may be an attahcment */
4620 if (src_folder == NULL)
4621 return GTK_RESPONSE_CANCEL;
4623 /* If the source is a local or MMC folder */
4624 if (!modest_tny_folder_is_remote_folder (src_folder)) {
4625 g_object_unref (src_folder);
4626 return GTK_RESPONSE_OK;
4629 /* Get the account */
4630 account = tny_folder_get_account (src_folder);
4632 /* now if offline we ask the user */
4633 if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4634 response = GTK_RESPONSE_OK;
4636 response = GTK_RESPONSE_CANCEL;
4639 g_object_unref (src_folder);
4640 g_object_unref (account);
4646 move_to_cb (ModestMailOperation *mail_op,
4649 MoveToHelper *helper = (MoveToHelper *) user_data;
4651 /* Note that the operation could have failed, in that case do
4653 if (modest_mail_operation_get_status (mail_op) ==
4654 MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4656 GObject *object = modest_mail_operation_get_source (mail_op);
4657 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4658 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4660 if (!modest_msg_view_window_select_next_message (self) &&
4661 !modest_msg_view_window_select_previous_message (self)) {
4662 /* No more messages to view, so close this window */
4663 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4665 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4666 GtkWidget *header_view;
4668 GtkTreeSelection *sel;
4670 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4671 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4672 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4673 path = gtk_tree_row_reference_get_path (helper->reference);
4674 /* We need to unselect the previous one
4675 because we could be copying instead of
4677 gtk_tree_selection_unselect_all (sel);
4678 gtk_tree_selection_select_path (sel, path);
4679 gtk_tree_path_free (path);
4681 g_object_unref (object);
4684 /* Close the "Pasting" information banner */
4685 if (helper->banner) {
4686 gtk_widget_destroy (GTK_WIDGET(helper->banner));
4687 g_object_unref (helper->banner);
4689 if (helper->reference != NULL)
4690 gtk_tree_row_reference_free (helper->reference);
4695 folder_move_to_cb (ModestMailOperation *mail_op,
4696 TnyFolder *new_folder,
4699 GtkWidget *folder_view;
4702 object = modest_mail_operation_get_source (mail_op);
4703 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4704 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4705 g_object_ref (folder_view);
4706 g_object_unref (object);
4707 move_to_cb (mail_op, user_data);
4708 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4709 g_object_unref (folder_view);
4713 msgs_move_to_cb (ModestMailOperation *mail_op,
4716 move_to_cb (mail_op, user_data);
4720 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4723 ModestWindow *main_window = NULL;
4725 /* Disable next automatic folder selection */
4726 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4727 FALSE); /* don't create */
4729 GObject *win = NULL;
4730 GtkWidget *folder_view = NULL;
4732 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4733 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4734 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4736 if (user_data && TNY_IS_FOLDER (user_data)) {
4737 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
4738 TNY_FOLDER (user_data), FALSE);
4741 /* Show notification dialog only if the main window exists */
4742 win = modest_mail_operation_get_source (mail_op);
4743 modest_platform_run_information_dialog ((GtkWindow *) win,
4744 _("mail_in_ui_folder_move_target_error"),
4747 g_object_unref (win);
4752 open_msg_for_purge_cb (ModestMailOperation *mail_op,
4761 gint pending_purges = 0;
4762 gboolean some_purged = FALSE;
4763 ModestWindow *win = MODEST_WINDOW (user_data);
4764 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4766 /* If there was any error */
4767 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4768 modest_window_mgr_unregister_header (mgr, header);
4772 /* Once the message has been retrieved for purging, we check if
4773 * it's all ok for purging */
4775 parts = tny_simple_list_new ();
4776 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4777 iter = tny_list_create_iterator (parts);
4779 while (!tny_iterator_is_done (iter)) {
4781 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4782 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4783 if (tny_mime_part_is_purged (part))
4790 g_object_unref (part);
4792 tny_iterator_next (iter);
4794 g_object_unref (iter);
4797 if (pending_purges>0) {
4799 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4801 if (response == GTK_RESPONSE_OK) {
4802 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4803 iter = tny_list_create_iterator (parts);
4804 while (!tny_iterator_is_done (iter)) {
4807 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4808 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4809 tny_mime_part_set_purged (part);
4812 g_object_unref (part);
4814 tny_iterator_next (iter);
4816 g_object_unref (iter);
4818 tny_msg_rewrite_cache (msg);
4821 /* This string no longer exists, refer to NB#75415 for more info */
4822 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4825 modest_window_mgr_unregister_header (mgr, header);
4827 g_object_unref (parts);
4831 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4832 ModestMainWindow *win)
4834 GtkWidget *header_view;
4835 TnyList *header_list;
4837 TnyHeaderFlags flags;
4838 ModestWindow *msg_view_window = NULL;
4841 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4843 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4844 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4846 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4848 g_warning ("%s: no header selected", __FUNCTION__);
4852 if (tny_list_get_length (header_list) == 1) {
4853 TnyIterator *iter = tny_list_create_iterator (header_list);
4854 header = TNY_HEADER (tny_iterator_get_current (iter));
4855 g_object_unref (iter);
4859 if (!header || !TNY_IS_HEADER(header)) {
4860 g_warning ("%s: header is not valid", __FUNCTION__);
4864 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4865 header, &msg_view_window);
4866 flags = tny_header_get_flags (header);
4867 if (!(flags & TNY_HEADER_FLAG_CACHED))
4870 if (msg_view_window != NULL)
4871 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4873 /* do nothing; uid was registered before, so window is probably on it's way */
4874 g_warning ("debug: header %p has already been registered", header);
4877 ModestMailOperation *mail_op = NULL;
4878 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4879 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4880 modest_ui_actions_disk_operations_error_handler,
4882 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4883 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
4885 g_object_unref (mail_op);
4888 g_object_unref (header);
4890 g_object_unref (header_list);
4894 * Checks if we need a connection to do the transfer and if the user
4895 * wants to connect to complete it
4898 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4899 TnyFolderStore *src_folder,
4901 TnyFolder *dst_folder,
4902 gboolean delete_originals,
4903 gboolean *need_connection,
4906 TnyAccount *src_account;
4907 gint uncached_msgs = 0;
4909 uncached_msgs = header_list_count_uncached_msgs (headers);
4911 /* We don't need any further check if
4913 * 1- the source folder is local OR
4914 * 2- the device is already online
4916 if (!modest_tny_folder_store_is_remote (src_folder) ||
4917 tny_device_is_online (modest_runtime_get_device())) {
4918 *need_connection = FALSE;
4923 /* We must ask for a connection when
4925 * - the message(s) is not already cached OR
4926 * - the message(s) is cached but the leave_on_server setting
4927 * is FALSE (because we need to sync the source folder to
4928 * delete the message from the server (for IMAP we could do it
4929 * offline, it'll take place the next time we get a
4932 src_account = get_account_from_folder_store (src_folder);
4933 if (uncached_msgs > 0) {
4937 *need_connection = TRUE;
4938 num_headers = tny_list_get_length (headers);
4939 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4941 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4942 GTK_RESPONSE_CANCEL) {
4948 /* The transfer is possible and the user wants to */
4951 if (remote_folder_is_pop (src_folder) && delete_originals) {
4952 const gchar *account_name;
4953 gboolean leave_on_server;
4955 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4956 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4959 if (leave_on_server == TRUE) {
4960 *need_connection = FALSE;
4962 *need_connection = TRUE;
4965 *need_connection = FALSE;
4970 g_object_unref (src_account);
4974 xfer_messages_error_handler (ModestMailOperation *mail_op,
4977 ModestWindow *main_window = NULL;
4979 /* Disable next automatic folder selection */
4980 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4981 FALSE); /* don't create */
4983 GObject *win = modest_mail_operation_get_source (mail_op);
4984 modest_platform_run_information_dialog ((GtkWindow *) win,
4985 _("mail_in_ui_folder_move_target_error"),
4988 g_object_unref (win);
4993 * Utility function that transfer messages from both the main window
4994 * and the msg view window when using the "Move to" dialog
4997 xfer_messages_performer (gboolean canceled,
4999 GtkWindow *parent_window,
5000 TnyAccount *account,
5003 TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
5004 ModestWindow *win = MODEST_WINDOW (parent_window);
5005 TnyList *headers = NULL;
5006 TnyAccount *dst_account = NULL;
5007 const gchar *proto_str = NULL;
5008 gboolean dst_is_pop = FALSE;
5014 if (is_memory_full_error (err)) {
5015 modest_platform_information_banner ((GtkWidget *) parent_window,
5016 NULL, dgettext("ke-recv",
5017 "cerm_device_memory_full"));
5019 /* Show the proper error message */
5020 modest_ui_actions_on_account_connection_error (parent_window, account);
5025 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5026 proto_str = tny_account_get_proto (dst_account);
5028 /* tinymail will return NULL for local folders it seems */
5029 dst_is_pop = proto_str &&
5030 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
5031 MODEST_PROTOCOL_STORE_POP);
5033 g_object_unref (dst_account);
5035 /* Get selected headers */
5036 headers = get_selected_headers (MODEST_WINDOW (win));
5038 g_warning ("%s: no headers selected", __FUNCTION__);
5043 modest_platform_information_banner (GTK_WIDGET (win),
5045 ngettext("mail_in_ui_folder_move_target_error",
5046 "mail_in_ui_folder_move_targets_error",
5047 tny_list_get_length (headers)));
5048 g_object_unref (headers);
5052 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5053 helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5054 _CS("ckct_nw_pasting"));
5055 if (helper->banner != NULL) {
5056 g_object_ref (helper->banner);
5057 gtk_widget_show (GTK_WIDGET(helper->banner));
5060 if (MODEST_IS_MAIN_WINDOW (win)) {
5061 GtkWidget *header_view =
5062 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5063 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5064 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5067 ModestMailOperation *mail_op =
5068 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5069 xfer_messages_error_handler,
5071 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5074 modest_mail_operation_xfer_msgs (mail_op,
5076 TNY_FOLDER (dst_folder),
5081 g_object_unref (G_OBJECT (mail_op));
5082 g_object_unref (headers);
5084 g_object_unref (dst_folder);
5088 TnyFolder *src_folder;
5089 TnyFolderStore *dst_folder;
5090 gboolean delete_original;
5091 GtkWidget *folder_view;
5095 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5096 TnyAccount *account, gpointer user_data)
5098 MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5099 GtkTreeSelection *sel;
5100 ModestMailOperation *mail_op = NULL;
5102 if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5103 g_object_unref (G_OBJECT (info->src_folder));
5104 g_object_unref (G_OBJECT (info->dst_folder));
5109 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5110 helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5111 _CS("ckct_nw_pasting"));
5112 if (helper->banner != NULL) {
5113 g_object_ref (helper->banner);
5114 gtk_widget_show (GTK_WIDGET(helper->banner));
5116 /* Clean folder on header view before moving it */
5117 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5118 gtk_tree_selection_unselect_all (sel);
5120 /* Let gtk events run. We need that the folder
5121 view frees its reference to the source
5122 folder *before* issuing the mail operation
5123 so we need the signal handler of selection
5124 changed to happen before the mail
5126 while (gtk_events_pending ())
5127 gtk_main_iteration (); */
5130 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5131 modest_ui_actions_move_folder_error_handler,
5132 info->src_folder, NULL);
5133 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5136 /* Select *after* the changes */
5137 /* TODO: this function hangs UI after transfer */
5138 /* modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5139 /* TNY_FOLDER (src_folder), TRUE); */
5141 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5142 TNY_FOLDER (info->dst_folder), TRUE);
5143 modest_mail_operation_xfer_folder (mail_op,
5144 TNY_FOLDER (info->src_folder),
5146 info->delete_original,
5149 g_object_unref (G_OBJECT (info->src_folder));
5151 /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) { */
5154 /* Unref mail operation */
5155 g_object_unref (G_OBJECT (mail_op));
5156 g_object_unref (G_OBJECT (info->dst_folder));
5161 get_account_from_folder_store (TnyFolderStore *folder_store)
5163 if (TNY_IS_ACCOUNT (folder_store))
5164 return g_object_ref (folder_store);
5166 return tny_folder_get_account (TNY_FOLDER (folder_store));
5170 * UI handler for the "Move to" action when invoked from the
5174 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5175 GtkWidget *folder_view,
5176 TnyFolderStore *dst_folder,
5177 ModestMainWindow *win)
5179 ModestHeaderView *header_view = NULL;
5180 TnyFolderStore *src_folder = NULL;
5182 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5184 /* Get the source folder */
5185 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5187 /* Get header view */
5188 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5190 /* Get folder or messages to transfer */
5191 if (gtk_widget_is_focus (folder_view)) {
5192 gboolean do_xfer = TRUE;
5194 /* Allow only to transfer folders to the local root folder */
5195 if (TNY_IS_ACCOUNT (dst_folder) &&
5196 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5197 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5199 } else if (!TNY_IS_FOLDER (src_folder)) {
5200 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5205 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5206 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5208 info->src_folder = g_object_ref (src_folder);
5209 info->dst_folder = g_object_ref (dst_folder);
5210 info->delete_original = TRUE;
5211 info->folder_view = folder_view;
5213 connect_info->callback = on_move_folder_cb;
5214 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5215 connect_info->data = info;
5217 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5218 TNY_FOLDER_STORE (src_folder),
5221 } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5224 headers = modest_header_view_get_selected_headers(header_view);
5226 /* Transfer the messages */
5227 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5228 headers, TNY_FOLDER (dst_folder));
5230 g_object_unref (headers);
5234 g_object_unref (src_folder);
5239 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5240 TnyFolder *src_folder,
5242 TnyFolder *dst_folder)
5244 gboolean need_connection = TRUE;
5245 gboolean do_xfer = TRUE;
5247 modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5248 headers, TNY_FOLDER (dst_folder),
5249 TRUE, &need_connection,
5252 /* If we don't want to transfer just return */
5256 if (need_connection) {
5257 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5258 connect_info->callback = xfer_messages_performer;
5259 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5260 connect_info->data = g_object_ref (dst_folder);
5262 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5263 TNY_FOLDER_STORE (src_folder),
5266 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5267 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5268 src_account, g_object_ref (dst_folder));
5269 g_object_unref (src_account);
5274 * UI handler for the "Move to" action when invoked from the
5275 * ModestMsgViewWindow
5278 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
5279 TnyFolderStore *dst_folder,
5280 ModestMsgViewWindow *win)
5282 TnyList *headers = NULL;
5283 TnyHeader *header = NULL;
5284 TnyFolder *src_folder = NULL;
5286 g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5288 /* Create header list */
5289 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5290 src_folder = TNY_FOLDER (tny_header_get_folder(header));
5291 headers = tny_simple_list_new ();
5292 tny_list_append (headers, G_OBJECT (header));
5294 /* Transfer the messages */
5295 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers,
5296 TNY_FOLDER (dst_folder));
5299 g_object_unref (header);
5300 g_object_unref (headers);
5304 modest_ui_actions_on_move_to (GtkAction *action,
5307 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5309 TnyFolderStore *dst_folder = NULL;
5310 ModestMainWindow *main_window;
5312 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5313 MODEST_IS_MSG_VIEW_WINDOW (win));
5315 /* Get the main window if exists */
5316 if (MODEST_IS_MAIN_WINDOW (win))
5317 main_window = MODEST_MAIN_WINDOW (win);
5320 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5321 FALSE)); /* don't create */
5323 /* Get the folder view widget if exists */
5325 folder_view = modest_main_window_get_child_widget (main_window,
5326 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5330 /* Create and run the dialog */
5331 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5332 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5333 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5334 result = gtk_dialog_run (GTK_DIALOG(dialog));
5335 g_object_ref (tree_view);
5336 gtk_widget_destroy (dialog);
5338 if (result != GTK_RESPONSE_ACCEPT)
5341 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5342 /* Do window specific stuff */
5343 if (MODEST_IS_MAIN_WINDOW (win)) {
5344 modest_ui_actions_on_main_window_move_to (action,
5347 MODEST_MAIN_WINDOW (win));
5349 modest_ui_actions_on_msg_view_window_move_to (action,
5351 MODEST_MSG_VIEW_WINDOW (win));
5355 g_object_unref (dst_folder);
5359 * Calls #HeadersFunc for each header already selected in the main
5360 * window or the message currently being shown in the msg view window
5363 do_headers_action (ModestWindow *win,
5367 TnyList *headers_list = NULL;
5368 TnyIterator *iter = NULL;
5369 TnyHeader *header = NULL;
5370 TnyFolder *folder = NULL;
5373 headers_list = get_selected_headers (win);
5377 /* Get the folder */
5378 iter = tny_list_create_iterator (headers_list);
5379 header = TNY_HEADER (tny_iterator_get_current (iter));
5381 folder = tny_header_get_folder (header);
5382 g_object_unref (header);
5385 /* Call the function for each header */
5386 while (!tny_iterator_is_done (iter)) {
5387 header = TNY_HEADER (tny_iterator_get_current (iter));
5388 func (header, win, user_data);
5389 g_object_unref (header);
5390 tny_iterator_next (iter);
5393 /* Trick: do a poke status in order to speed up the signaling
5395 tny_folder_poke_status (folder);
5398 g_object_unref (folder);
5399 g_object_unref (iter);
5400 g_object_unref (headers_list);
5404 modest_ui_actions_view_attachment (GtkAction *action,
5405 ModestWindow *window)
5407 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5408 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5410 /* not supported window for this action */
5411 g_return_if_reached ();
5416 modest_ui_actions_save_attachments (GtkAction *action,
5417 ModestWindow *window)
5419 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5421 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
5424 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5426 /* not supported window for this action */
5427 g_return_if_reached ();
5432 modest_ui_actions_remove_attachments (GtkAction *action,
5433 ModestWindow *window)
5435 if (MODEST_IS_MAIN_WINDOW (window)) {
5436 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5437 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5438 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5440 /* not supported window for this action */
5441 g_return_if_reached ();
5446 modest_ui_actions_on_settings (GtkAction *action,
5451 dialog = modest_platform_get_global_settings_dialog ();
5452 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5453 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5454 gtk_widget_show_all (dialog);
5456 gtk_dialog_run (GTK_DIALOG (dialog));
5458 gtk_widget_destroy (dialog);
5462 modest_ui_actions_on_help (GtkAction *action,
5465 const gchar *help_id;
5467 g_return_if_fail (action);
5468 g_return_if_fail (win && GTK_IS_WINDOW(win));
5470 help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5473 modest_platform_show_help (GTK_WINDOW (win), help_id);
5475 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5479 retrieve_msg_contents_performer (gboolean canceled,
5481 GtkWindow *parent_window,
5482 TnyAccount *account,
5485 ModestMailOperation *mail_op;
5486 TnyList *headers = TNY_LIST (user_data);
5488 if (err || canceled) {
5489 if (err && is_memory_full_error (err)) {
5490 modest_platform_information_banner ((GtkWidget *) parent_window,
5491 NULL, dgettext("ke-recv",
5492 "cerm_device_memory_full"));
5497 /* Create mail operation */
5498 mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5499 modest_ui_actions_disk_operations_error_handler,
5501 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5502 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5505 g_object_unref (mail_op);
5507 g_object_unref (headers);
5508 g_object_unref (account);
5512 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5513 ModestWindow *window)
5515 TnyList *headers = NULL;
5516 TnyAccount *account = NULL;
5517 TnyIterator *iter = NULL;
5518 TnyHeader *header = NULL;
5519 TnyFolder *folder = NULL;
5522 headers = get_selected_headers (window);
5526 /* Pick the account */
5527 iter = tny_list_create_iterator (headers);
5528 header = TNY_HEADER (tny_iterator_get_current (iter));
5529 folder = tny_header_get_folder (header);
5530 account = tny_folder_get_account (folder);
5531 g_object_unref (folder);
5532 g_object_unref (header);
5533 g_object_unref (iter);
5535 /* Connect and perform the message retrieval */
5536 modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5537 g_object_ref (account),
5538 retrieve_msg_contents_performer,
5539 g_object_ref (headers));
5542 g_object_unref (account);
5543 g_object_unref (headers);
5547 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5549 g_return_if_fail (MODEST_IS_WINDOW (window));
5552 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5556 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5558 g_return_if_fail (MODEST_IS_WINDOW (window));
5561 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5565 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5566 ModestWindow *window)
5568 g_return_if_fail (MODEST_IS_WINDOW (window));
5571 modest_ui_actions_check_menu_dimming_rules (window);
5575 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5576 ModestWindow *window)
5578 g_return_if_fail (MODEST_IS_WINDOW (window));
5581 modest_ui_actions_check_menu_dimming_rules (window);
5585 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5586 ModestWindow *window)
5588 g_return_if_fail (MODEST_IS_WINDOW (window));
5591 modest_ui_actions_check_menu_dimming_rules (window);
5595 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5596 ModestWindow *window)
5598 g_return_if_fail (MODEST_IS_WINDOW (window));
5601 modest_ui_actions_check_menu_dimming_rules (window);
5605 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5606 ModestWindow *window)
5608 g_return_if_fail (MODEST_IS_WINDOW (window));
5611 modest_ui_actions_check_menu_dimming_rules (window);
5615 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5616 ModestWindow *window)
5618 g_return_if_fail (MODEST_IS_WINDOW (window));
5621 modest_ui_actions_check_menu_dimming_rules (window);
5625 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5626 ModestWindow *window)
5628 g_return_if_fail (MODEST_IS_WINDOW (window));
5631 modest_ui_actions_check_menu_dimming_rules (window);
5635 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5636 ModestWindow *window)
5638 g_return_if_fail (MODEST_IS_WINDOW (window));
5641 modest_ui_actions_check_menu_dimming_rules (window);
5645 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5646 ModestWindow *window)
5648 g_return_if_fail (MODEST_IS_WINDOW (window));
5651 modest_ui_actions_check_menu_dimming_rules (window);
5655 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5657 g_return_if_fail (MODEST_IS_WINDOW (window));
5659 /* we check for low-mem; in that case, show a warning, and don't allow
5662 if (modest_platform_check_memory_low (window))
5665 modest_platform_show_search_messages (GTK_WINDOW (window));
5669 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5671 g_return_if_fail (MODEST_IS_WINDOW (win));
5674 /* we check for low-mem; in that case, show a warning, and don't allow
5675 * for the addressbook
5677 if (modest_platform_check_memory_low (win))
5681 modest_platform_show_addressbook (GTK_WINDOW (win));
5686 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5687 ModestWindow *window)
5689 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5691 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5695 on_send_receive_finished (ModestMailOperation *mail_op,
5698 GtkWidget *header_view, *folder_view;
5699 TnyFolderStore *folder_store;
5700 ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5702 /* Set send/receive operation finished */
5703 modest_main_window_notify_send_receive_completed (main_win);
5705 /* Don't refresh the current folder if there were any errors */
5706 if (modest_mail_operation_get_status (mail_op) !=
5707 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5710 /* Refresh the current folder if we're viewing a window. We do
5711 this because the user won't be able to see the new mails in
5712 the selected folder after a Send&Receive because it only
5713 performs a poke_status, i.e, only the number of read/unread
5714 messages is updated, but the new headers are not
5716 folder_view = modest_main_window_get_child_widget (main_win,
5717 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5721 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5723 /* Do not need to refresh INBOX again because the
5724 update_account does it always automatically */
5725 if (folder_store && TNY_IS_FOLDER (folder_store) &&
5726 tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5727 ModestMailOperation *refresh_op;
5729 header_view = modest_main_window_get_child_widget (main_win,
5730 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5732 /* We do not need to set the contents style
5733 because it hasn't changed. We also do not
5734 need to save the widget status. Just force
5736 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5737 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5738 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5739 folder_refreshed_cb, main_win);
5740 g_object_unref (refresh_op);
5744 g_object_unref (folder_store);
5749 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5755 const gchar* server_name = NULL;
5756 TnyTransportAccount *server_account;
5757 gchar *message = NULL;
5759 /* Don't show anything if the user cancelled something or the send receive request is not
5761 if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5762 !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5766 /* Get the server name: */
5768 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5770 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5772 g_return_if_reached ();
5774 /* Show the appropriate message text for the GError: */
5775 switch (err->code) {
5776 case TNY_SERVICE_ERROR_CONNECT:
5777 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5779 case TNY_SERVICE_ERROR_AUTHENTICATE:
5780 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5782 case TNY_SERVICE_ERROR_SEND:
5783 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5785 case TNY_SERVICE_ERROR_UNAVAILABLE:
5786 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5789 g_warning ("%s: unexpected ERROR %d",
5790 __FUNCTION__, err->code);
5791 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5795 /* TODO if the username or the password where not defined we
5796 should show the Accounts Settings dialog or the Connection
5797 specific SMTP server window */
5799 modest_platform_run_information_dialog (NULL, message, FALSE);
5801 g_object_unref (server_account);
5805 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5810 ModestMainWindow *main_window = NULL;
5811 ModestWindowMgr *mgr = NULL;
5812 GtkWidget *folder_view = NULL, *header_view = NULL;
5813 TnyFolderStore *selected_folder = NULL;
5814 TnyFolderType folder_type;
5816 mgr = modest_runtime_get_window_mgr ();
5817 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5818 FALSE));/* don't create */
5822 /* Check if selected folder is OUTBOX */
5823 folder_view = modest_main_window_get_child_widget (main_window,
5824 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5825 header_view = modest_main_window_get_child_widget (main_window,
5826 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5828 selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5829 if (!TNY_IS_FOLDER (selected_folder))
5832 /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5833 #if GTK_CHECK_VERSION(2, 8, 0)
5834 folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder));
5835 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
5836 GtkTreeViewColumn *tree_column;
5838 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5839 TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5840 gtk_tree_view_column_queue_resize (tree_column);
5843 gtk_widget_queue_draw (header_view);
5846 /* Rerun dimming rules, because the message could become deletable for example */
5847 modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window),
5848 MODEST_DIMMING_RULES_TOOLBAR);
5852 if (selected_folder != NULL)
5853 g_object_unref (selected_folder);
5857 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5858 TnyAccount *account)
5860 ModestTransportStoreProtocol proto;
5861 const gchar *proto_name;
5862 gchar *error_note = NULL;
5864 proto_name = tny_account_get_proto (account);
5865 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5868 case MODEST_PROTOCOL_STORE_POP:
5869 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"),
5870 tny_account_get_hostname (account));
5872 case MODEST_PROTOCOL_STORE_IMAP:
5873 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"),
5874 tny_account_get_hostname (account));
5876 case MODEST_PROTOCOL_STORE_MAILDIR:
5877 case MODEST_PROTOCOL_STORE_MBOX:
5878 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5881 g_warning ("%s: This should not be reached", __FUNCTION__);
5885 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5886 g_free (error_note);
5891 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5894 TnyFolderStore *folder = NULL;
5895 TnyAccount *account = NULL;
5896 ModestTransportStoreProtocol proto;
5897 TnyHeader *header = NULL;
5899 if (MODEST_IS_MAIN_WINDOW (win)) {
5900 GtkWidget *header_view;
5901 TnyList* headers = NULL;
5903 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5904 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5905 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5906 if (!headers || tny_list_get_length (headers) == 0) {
5908 g_object_unref (headers);
5911 iter = tny_list_create_iterator (headers);
5912 header = TNY_HEADER (tny_iterator_get_current (iter));
5913 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5914 g_object_unref (iter);
5915 g_object_unref (headers);
5916 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5917 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5918 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5921 /* Get the account type */
5922 account = tny_folder_get_account (TNY_FOLDER (folder));
5923 proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5924 if (proto == MODEST_PROTOCOL_STORE_POP) {
5925 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5926 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5928 subject = tny_header_dup_subject (header);
5929 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
5933 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5937 g_object_unref (account);
5938 g_object_unref (folder);
5939 g_object_unref (header);