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 ());
651 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
653 /* The accounts dialog must be modal */
654 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
655 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
659 #ifdef MODEST_PLATFORM_MAEMO
661 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
663 /* Save any changes. */
664 modest_connection_specific_smtp_window_save_server_accounts (
665 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
666 gtk_widget_destroy (GTK_WIDGET (window));
672 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
674 /* This is currently only implemented for Maemo,
675 * because it requires an API (libconic) to detect different connection
678 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
680 /* Create the window if necessary: */
681 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
682 modest_connection_specific_smtp_window_fill_with_connections (
683 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
684 modest_runtime_get_account_mgr());
686 /* Show the window: */
687 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
688 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
689 gtk_widget_show (specific_window);
691 /* Save changes when the window is hidden: */
692 g_signal_connect (specific_window, "hide",
693 G_CALLBACK (on_smtp_servers_window_hide), win);
694 #endif /* MODEST_PLATFORM_MAEMO */
698 modest_ui_actions_compose_msg(ModestWindow *win,
701 const gchar *bcc_str,
702 const gchar *subject_str,
703 const gchar *body_str,
705 gboolean set_as_modified)
707 gchar *account_name = NULL;
709 TnyAccount *account = NULL;
710 TnyFolder *folder = NULL;
711 gchar *from_str = NULL, *signature = NULL, *body = NULL;
712 gboolean use_signature = FALSE;
713 ModestWindow *msg_win = NULL;
714 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
715 ModestTnyAccountStore *store = modest_runtime_get_account_store();
716 GnomeVFSFileSize total_size, allowed_size;
718 /* we check for low-mem; in that case, show a warning, and don't allow
719 * composing a message with attachments
721 if (attachments && modest_platform_check_memory_low (win))
724 account_name = modest_account_mgr_get_default_account(mgr);
726 g_printerr ("modest: no account found\n");
729 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
731 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
734 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
736 g_printerr ("modest: failed to find Drafts folder\n");
739 from_str = modest_account_mgr_get_from_string (mgr, account_name);
741 g_printerr ("modest: failed get from string for '%s'\n", account_name);
745 signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
746 if (body_str != NULL) {
747 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
749 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
752 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
754 g_printerr ("modest: failed to create new msg\n");
758 /* Create and register edit window */
759 /* This is destroyed by TODO. */
761 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
762 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
763 while (attachments) {
765 modest_msg_edit_window_attach_file_one(
766 (ModestMsgEditWindow *)msg_win,
767 attachments->data, allowed_size);
769 if (total_size > allowed_size) {
770 g_warning ("%s: total size: %u",
771 __FUNCTION__, (unsigned int)total_size);
774 allowed_size -= total_size;
776 attachments = g_slist_next(attachments);
778 modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
779 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
781 gtk_widget_show_all (GTK_WIDGET (msg_win));
787 g_free (account_name);
789 g_object_unref (G_OBJECT(account));
791 g_object_unref (G_OBJECT(folder));
793 g_object_unref (G_OBJECT(msg_win));
795 g_object_unref (G_OBJECT(msg));
799 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
801 /* if there are no accounts yet, just show the wizard */
802 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
803 if (!modest_ui_actions_run_account_setup_wizard (win))
806 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
811 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
815 ModestMailOperationStatus status;
817 /* If there is no message or the operation was not successful */
818 status = modest_mail_operation_get_status (mail_op);
819 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
821 /* Remove the header from the preregistered uids */
822 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
840 OpenMsgBannerInfo *banner_info;
841 GHashTable *row_refs_per_header;
845 open_msg_banner_idle (gpointer userdata)
847 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
849 gdk_threads_enter ();
850 banner_info->idle_handler = 0;
851 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);
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 for (node = accounts; node != NULL; node = g_slist_next (node)) {
949 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
951 if (from && (strcmp (from_header, from) == 0)) {
953 account = g_strdup (node->data);
959 g_free (from_header);
960 g_slist_foreach (accounts, (GFunc) g_free, NULL);
961 g_slist_free (accounts);
964 win = modest_msg_edit_window_new (msg, account, TRUE);
969 gchar *uid = modest_tny_folder_get_header_unique_id (header);
971 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
972 GtkTreeRowReference *row_reference;
974 row_reference = (GtkTreeRowReference *) g_hash_table_lookup (helper->row_refs_per_header, header);
976 win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
977 helper->model, row_reference);
979 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
984 /* Register and show new window */
986 mgr = modest_runtime_get_window_mgr ();
987 modest_window_mgr_register_window (mgr, win);
988 g_object_unref (win);
989 gtk_widget_show_all (GTK_WIDGET(win));
992 /* Update toolbar dimming state */
993 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
994 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1000 g_object_unref (parent_win);
1001 g_object_unref (folder);
1005 is_memory_full_error (GError *error)
1007 if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
1008 error->code == TNY_IO_ERROR_WRITE ||
1009 error->code == TNY_IO_ERROR_READ) {
1017 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1020 const GError *error;
1021 GObject *win = NULL;
1022 ModestMailOperationStatus status;
1024 win = modest_mail_operation_get_source (mail_op);
1025 error = modest_mail_operation_get_error (mail_op);
1026 status = modest_mail_operation_get_status (mail_op);
1028 /* If the mail op has been cancelled then it's not an error:
1029 don't show any message */
1030 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1031 if (is_memory_full_error ((GError *) error)) {
1032 modest_platform_information_banner ((GtkWidget *) win,
1033 NULL, dgettext("ke-recv",
1034 "cerm_device_memory_full"));
1035 } else if (user_data) {
1036 modest_platform_information_banner ((GtkWidget *) win,
1042 g_object_unref (win);
1046 * Returns the account a list of headers belongs to. It returns a
1047 * *new* reference so don't forget to unref it
1050 get_account_from_header_list (TnyList *headers)
1052 TnyAccount *account = NULL;
1054 if (tny_list_get_length (headers) > 0) {
1055 TnyIterator *iter = tny_list_create_iterator (headers);
1056 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1057 TnyFolder *folder = tny_header_get_folder (header);
1060 g_object_unref (header);
1062 while (!tny_iterator_is_done (iter)) {
1063 header = TNY_HEADER (tny_iterator_get_current (iter));
1064 folder = tny_header_get_folder (header);
1067 g_object_unref (header);
1069 tny_iterator_next (iter);
1074 account = tny_folder_get_account (folder);
1075 g_object_unref (folder);
1079 g_object_unref (header);
1081 g_object_unref (iter);
1087 foreach_unregister_headers (gpointer data,
1090 ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1091 TnyHeader *header = TNY_HEADER (data);
1093 modest_window_mgr_unregister_header (mgr, header);
1097 open_msgs_helper_destroyer (gpointer user_data)
1099 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1101 if (helper->banner_info) {
1102 g_free (helper->banner_info->message);
1103 if (helper->banner_info->idle_handler > 0) {
1104 g_source_remove (helper->banner_info->idle_handler);
1105 helper->banner_info->idle_handler = 0;
1107 if (helper->banner_info->banner != NULL) {
1108 gtk_widget_destroy (helper->banner_info->banner);
1109 g_object_unref (helper->banner_info->banner);
1110 helper->banner_info->banner = NULL;
1112 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1113 helper->banner_info = NULL;
1115 g_object_unref (helper->model);
1116 g_object_unref (helper->headers);
1117 g_hash_table_destroy (helper->row_refs_per_header);
1118 g_slice_free (OpenMsgHelper, helper);
1122 open_msgs_performer(gboolean canceled,
1124 GtkWindow *parent_window,
1125 TnyAccount *account,
1128 ModestMailOperation *mail_op = NULL;
1129 const gchar *proto_name;
1131 ModestTransportStoreProtocol proto;
1132 TnyList *not_opened_headers;
1133 TnyConnectionStatus status;
1134 gboolean show_open_draft = FALSE;
1135 OpenMsgHelper *helper = NULL;
1137 helper = (OpenMsgHelper *) user_data;
1138 not_opened_headers = helper->headers;
1140 status = tny_account_get_connection_status (account);
1141 if (err || canceled) {
1142 /* Unregister the already registered headers */
1143 tny_list_foreach (not_opened_headers, foreach_unregister_headers,
1144 modest_runtime_get_window_mgr ());
1145 /* Free the helper */
1146 open_msgs_helper_destroyer (helper);
1148 /* In memory full conditions we could get this error here */
1149 if (err && is_memory_full_error (err)) {
1150 modest_platform_information_banner ((GtkWidget *) parent_window,
1151 NULL, dgettext("ke-recv",
1152 "cerm_device_memory_full"));
1157 /* Get the error message depending on the protocol */
1158 proto_name = tny_account_get_proto (account);
1159 if (proto_name != NULL) {
1160 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1162 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1165 /* Create the error messages */
1166 if (tny_list_get_length (not_opened_headers) == 1) {
1167 if (proto == MODEST_PROTOCOL_STORE_POP) {
1168 error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1169 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1170 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1171 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1172 gchar *subject = tny_header_dup_subject (header);
1173 error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1176 g_object_unref (header);
1177 g_object_unref (iter);
1182 TnyFolderType folder_type;
1184 iter = tny_list_create_iterator (not_opened_headers);
1185 header = TNY_HEADER (tny_iterator_get_current (iter));
1186 folder = tny_header_get_folder (header);
1187 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1188 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1189 g_object_unref (folder);
1190 g_object_unref (header);
1191 g_object_unref (iter);
1192 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1195 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1198 /* Create the mail operation */
1200 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1201 modest_ui_actions_disk_operations_error_handler,
1203 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1206 if (show_open_draft) {
1207 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1208 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1209 helper->banner_info->banner = NULL;
1210 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1211 helper->banner_info);
1214 modest_mail_operation_get_msgs_full (mail_op,
1218 open_msgs_helper_destroyer);
1223 g_object_unref (mail_op);
1224 g_object_unref (account);
1228 * This function is used by both modest_ui_actions_on_open and
1229 * modest_ui_actions_on_header_activated. This way we always do the
1230 * same when trying to open messages.
1233 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1235 ModestWindowMgr *mgr = NULL;
1236 TnyIterator *iter = NULL, *iter_not_opened = NULL;
1237 TnyList *not_opened_headers = NULL;
1238 TnyHeaderFlags flags = 0;
1239 TnyAccount *account;
1240 gint uncached_msgs = 0;
1241 GtkWidget *header_view;
1242 GtkTreeModel *model;
1243 GHashTable *refs_for_headers;
1244 OpenMsgHelper *helper;
1245 GtkTreeSelection *sel;
1246 GList *sel_list = NULL, *sel_list_iter = NULL;
1248 g_return_if_fail (headers != NULL);
1250 /* Check that only one message is selected for opening */
1251 if (tny_list_get_length (headers) != 1) {
1252 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1253 NULL, _("mcen_ib_select_one_message"));
1257 mgr = modest_runtime_get_window_mgr ();
1258 iter = tny_list_create_iterator (headers);
1260 /* Get the account */
1261 account = get_account_from_header_list (headers);
1266 /* Get the selections, we need to get the references to the
1267 rows here because the treeview/model could dissapear (the
1268 user might want to select another folder)*/
1269 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1270 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1271 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1272 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
1273 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1274 refs_for_headers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1275 (GDestroyNotify) gtk_tree_row_reference_free);
1277 /* Look if we already have a message view for each header. If
1278 true, then remove the header from the list of headers to
1280 sel_list_iter = sel_list;
1281 not_opened_headers = tny_simple_list_new ();
1282 while (!tny_iterator_is_done (iter) && sel_list_iter) {
1284 ModestWindow *window = NULL;
1285 TnyHeader *header = NULL;
1286 gboolean found = FALSE;
1288 header = TNY_HEADER (tny_iterator_get_current (iter));
1290 flags = tny_header_get_flags (header);
1293 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1295 /* Do not open again the message and present the
1296 window to the user */
1299 gtk_window_present (GTK_WINDOW (window));
1301 /* the header has been registered already, we don't do
1302 * anything but wait for the window to come up*/
1303 g_debug ("header %p already registered, waiting for window", header);
1306 GtkTreeRowReference *row_reference;
1308 tny_list_append (not_opened_headers, G_OBJECT (header));
1309 /* Create a new row reference and add it to the hash table */
1310 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list_iter->data);
1311 g_hash_table_insert (refs_for_headers, header, row_reference);
1315 g_object_unref (header);
1318 tny_iterator_next (iter);
1319 sel_list_iter = g_list_next (sel_list_iter);
1321 g_object_unref (iter);
1323 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1324 g_list_free (sel_list);
1326 /* Open each message */
1327 if (tny_list_get_length (not_opened_headers) == 0) {
1328 g_hash_table_destroy (refs_for_headers);
1332 /* If some messages would have to be downloaded, ask the user to
1333 * make a connection. It's generally easier to do this here (in the mainloop)
1334 * than later in a thread:
1336 if (tny_list_get_length (not_opened_headers) > 0) {
1337 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1339 if (uncached_msgs > 0) {
1340 /* Allways download if we are online. */
1341 if (!tny_device_is_online (modest_runtime_get_device ())) {
1344 /* If ask for user permission to download the messages */
1345 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1346 ngettext("mcen_nc_get_msg",
1350 /* End if the user does not want to continue */
1351 if (response == GTK_RESPONSE_CANCEL) {
1352 g_hash_table_destroy (refs_for_headers);
1359 /* Register the headers before actually creating the windows: */
1360 iter_not_opened = tny_list_create_iterator (not_opened_headers);
1361 while (!tny_iterator_is_done (iter_not_opened)) {
1362 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1364 modest_window_mgr_register_header (mgr, header, NULL);
1365 g_object_unref (header);
1367 tny_iterator_next (iter_not_opened);
1369 g_object_unref (iter_not_opened);
1370 iter_not_opened = NULL;
1372 /* Create the helper. We need to get a reference to the model
1373 here because it could change while the message is readed
1374 (the user could switch between folders) */
1375 helper = g_slice_new (OpenMsgHelper);
1376 helper->model = g_object_ref (model);
1377 helper->headers = g_object_ref (not_opened_headers);
1378 helper->row_refs_per_header = refs_for_headers;
1379 helper->banner_info = NULL;
1381 /* Connect to the account and perform */
1382 if (uncached_msgs > 0) {
1383 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1384 open_msgs_performer, helper);
1386 /* Call directly the performer, do not need to connect */
1387 open_msgs_performer (FALSE, NULL, (GtkWindow *) win,
1388 g_object_ref (account), helper);
1393 g_object_unref (account);
1394 if (not_opened_headers)
1395 g_object_unref (not_opened_headers);
1399 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1403 /* we check for low-mem; in that case, show a warning, and don't allow
1406 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1410 headers = get_selected_headers (win);
1415 open_msgs_from_headers (headers, win);
1417 g_object_unref(headers);
1422 free_reply_forward_helper (gpointer data)
1424 ReplyForwardHelper *helper;
1426 helper = (ReplyForwardHelper *) data;
1427 g_free (helper->account_name);
1428 g_slice_free (ReplyForwardHelper, helper);
1432 reply_forward_cb (ModestMailOperation *mail_op,
1440 ReplyForwardHelper *rf_helper;
1441 ModestWindow *msg_win = NULL;
1442 ModestEditType edit_type;
1444 TnyAccount *account = NULL;
1445 ModestWindowMgr *mgr = NULL;
1446 gchar *signature = NULL;
1447 gboolean use_signature;
1449 /* If there was any error. The mail operation could be NULL,
1450 this means that we already have the message downloaded and
1451 that we didn't do a mail operation to retrieve it */
1452 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1455 g_return_if_fail (user_data != NULL);
1456 rf_helper = (ReplyForwardHelper *) user_data;
1458 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1459 rf_helper->account_name);
1460 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(),
1461 rf_helper->account_name,
1464 /* Create reply mail */
1465 switch (rf_helper->action) {
1468 modest_tny_msg_create_reply_msg (msg, header, from,
1469 (use_signature) ? signature : NULL,
1470 rf_helper->reply_forward_type,
1471 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1473 case ACTION_REPLY_TO_ALL:
1475 modest_tny_msg_create_reply_msg (msg, header, from,
1476 (use_signature) ? signature : NULL,
1477 rf_helper->reply_forward_type,
1478 MODEST_TNY_MSG_REPLY_MODE_ALL);
1479 edit_type = MODEST_EDIT_TYPE_REPLY;
1481 case ACTION_FORWARD:
1483 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1484 rf_helper->reply_forward_type);
1485 edit_type = MODEST_EDIT_TYPE_FORWARD;
1488 g_return_if_reached ();
1495 g_printerr ("modest: failed to create message\n");
1499 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1500 rf_helper->account_name,
1501 TNY_ACCOUNT_TYPE_STORE);
1503 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1507 /* Create and register the windows */
1508 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1509 mgr = modest_runtime_get_window_mgr ();
1510 modest_window_mgr_register_window (mgr, msg_win);
1512 if (rf_helper->parent_window != NULL) {
1513 gdouble parent_zoom;
1515 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1516 modest_window_set_zoom (msg_win, parent_zoom);
1519 /* Show edit window */
1520 gtk_widget_show_all (GTK_WIDGET (msg_win));
1524 g_object_unref (msg_win);
1526 g_object_unref (G_OBJECT (new_msg));
1528 g_object_unref (G_OBJECT (account));
1529 /* g_object_unref (msg); */
1530 free_reply_forward_helper (rf_helper);
1533 /* Checks a list of headers. If any of them are not currently
1534 * downloaded (CACHED) then returns TRUE else returns FALSE.
1537 header_list_count_uncached_msgs (TnyList *header_list)
1540 gint uncached_messages = 0;
1542 iter = tny_list_create_iterator (header_list);
1543 while (!tny_iterator_is_done (iter)) {
1546 header = TNY_HEADER (tny_iterator_get_current (iter));
1548 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1549 uncached_messages ++;
1550 g_object_unref (header);
1553 tny_iterator_next (iter);
1555 g_object_unref (iter);
1557 return uncached_messages;
1560 /* Returns FALSE if the user does not want to download the
1561 * messages. Returns TRUE if the user allowed the download.
1564 connect_to_get_msg (ModestWindow *win,
1565 gint num_of_uncached_msgs,
1566 TnyAccount *account)
1568 GtkResponseType response;
1570 /* Allways download if we are online. */
1571 if (tny_device_is_online (modest_runtime_get_device ()))
1574 /* If offline, then ask for user permission to download the messages */
1575 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1576 ngettext("mcen_nc_get_msg",
1578 num_of_uncached_msgs));
1580 if (response == GTK_RESPONSE_CANCEL)
1583 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1587 * Common code for the reply and forward actions
1590 reply_forward (ReplyForwardAction action, ModestWindow *win)
1592 ModestMailOperation *mail_op = NULL;
1593 TnyList *header_list = NULL;
1594 ReplyForwardHelper *rf_helper = NULL;
1595 guint reply_forward_type;
1596 gboolean continue_download = TRUE;
1597 gboolean do_retrieve = TRUE;
1599 g_return_if_fail (MODEST_IS_WINDOW(win));
1602 /* we check for low-mem; in that case, show a warning, and don't allow
1603 * reply/forward (because it could potentially require a lot of memory */
1604 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1608 /* we need an account when editing */
1609 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1610 if (!modest_ui_actions_run_account_setup_wizard (win))
1614 header_list = get_selected_headers (win);
1618 reply_forward_type =
1619 modest_conf_get_int (modest_runtime_get_conf (),
1620 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1623 /* check if we need to download msg before asking about it */
1624 do_retrieve = (action == ACTION_FORWARD) ||
1625 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1628 gint num_of_unc_msgs;
1630 /* check that the messages have been previously downloaded */
1631 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1632 /* If there are any uncached message ask the user
1633 * whether he/she wants to download them. */
1634 if (num_of_unc_msgs) {
1635 TnyAccount *account = get_account_from_header_list (header_list);
1637 continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1638 g_object_unref (account);
1643 if (!continue_download) {
1644 g_object_unref (header_list);
1648 /* We assume that we can only select messages of the
1649 same folder and that we reply all of them from the
1650 same account. In fact the interface currently only
1651 allows single selection */
1654 rf_helper = g_slice_new0 (ReplyForwardHelper);
1655 rf_helper->reply_forward_type = reply_forward_type;
1656 rf_helper->action = action;
1657 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1659 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1660 rf_helper->parent_window = GTK_WIDGET (win);
1661 if (!rf_helper->account_name)
1662 rf_helper->account_name =
1663 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1665 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1668 /* Get header and message. Do not free them here, the
1669 reply_forward_cb must do it */
1670 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1671 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1672 if (!msg || !header) {
1674 g_object_unref (msg);
1675 g_printerr ("modest: no message found\n");
1678 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1681 g_object_unref (header);
1686 /* Only reply/forward to one message */
1687 iter = tny_list_create_iterator (header_list);
1688 header = TNY_HEADER (tny_iterator_get_current (iter));
1689 g_object_unref (iter);
1692 /* Retrieve messages */
1695 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1696 modest_ui_actions_disk_operations_error_handler,
1698 modest_mail_operation_queue_add (
1699 modest_runtime_get_mail_operation_queue (), mail_op);
1701 modest_mail_operation_get_msg (mail_op,
1706 g_object_unref(mail_op);
1708 /* we put a ref here to prevent double unref as the reply
1709 * forward callback unrefs the header at its end */
1710 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1714 g_object_unref (header);
1720 g_object_unref (header_list);
1724 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1726 g_return_if_fail (MODEST_IS_WINDOW(win));
1728 reply_forward (ACTION_REPLY, win);
1732 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1734 g_return_if_fail (MODEST_IS_WINDOW(win));
1736 reply_forward (ACTION_FORWARD, win);
1740 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1742 g_return_if_fail (MODEST_IS_WINDOW(win));
1744 reply_forward (ACTION_REPLY_TO_ALL, win);
1748 modest_ui_actions_on_next (GtkAction *action,
1749 ModestWindow *window)
1751 if (MODEST_IS_MAIN_WINDOW (window)) {
1752 GtkWidget *header_view;
1754 header_view = modest_main_window_get_child_widget (
1755 MODEST_MAIN_WINDOW(window),
1756 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1760 modest_header_view_select_next (
1761 MODEST_HEADER_VIEW(header_view));
1762 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1763 modest_msg_view_window_select_next_message (
1764 MODEST_MSG_VIEW_WINDOW (window));
1766 g_return_if_reached ();
1771 modest_ui_actions_on_prev (GtkAction *action,
1772 ModestWindow *window)
1774 g_return_if_fail (MODEST_IS_WINDOW(window));
1776 if (MODEST_IS_MAIN_WINDOW (window)) {
1777 GtkWidget *header_view;
1778 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1779 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1783 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1784 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1785 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1787 g_return_if_reached ();
1792 modest_ui_actions_on_sort (GtkAction *action,
1793 ModestWindow *window)
1795 g_return_if_fail (MODEST_IS_WINDOW(window));
1797 if (MODEST_IS_MAIN_WINDOW (window)) {
1798 GtkWidget *header_view;
1799 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1800 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1802 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1807 /* Show sorting dialog */
1808 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1813 new_messages_arrived (ModestMailOperation *self,
1814 TnyList *new_headers,
1818 gboolean show_visual_notifications;
1820 source = modest_mail_operation_get_source (self);
1821 show_visual_notifications = (source) ? FALSE : TRUE;
1823 g_object_unref (source);
1825 /* Notify new messages have been downloaded. If the
1826 send&receive was invoked by the user then do not show any
1827 visual notification, only play a sound and activate the LED
1828 (for the Maemo version) */
1829 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1830 modest_platform_on_new_headers_received (new_headers,
1831 show_visual_notifications);
1836 retrieve_all_messages_cb (GObject *source,
1838 guint retrieve_limit)
1844 window = GTK_WINDOW (source);
1845 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
1846 num_msgs, retrieve_limit);
1848 /* Ask the user if they want to retrieve all the messages */
1850 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1851 _("mcen_bd_get_all"),
1852 _("mcen_bd_newest_only"));
1853 /* Free and return */
1855 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1859 TnyAccount *account;
1861 gchar *account_name;
1862 gboolean poke_status;
1863 gboolean interactive;
1864 ModestMailOperation *mail_op;
1868 do_send_receive_performer (gboolean canceled,
1870 GtkWindow *parent_window,
1871 TnyAccount *account,
1874 SendReceiveInfo *info;
1876 info = (SendReceiveInfo *) user_data;
1878 if (err || canceled) {
1879 /* In memory full conditions we could get this error here */
1880 if (err && is_memory_full_error (err)) {
1881 modest_platform_information_banner ((GtkWidget *) parent_window,
1882 NULL, dgettext("ke-recv",
1883 "cerm_device_memory_full"));
1885 if (info->mail_op) {
1886 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
1892 /* Set send/receive operation in progress */
1893 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1894 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1897 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1898 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
1899 G_CALLBACK (on_send_receive_finished),
1902 /* Send & receive. */
1903 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
1904 (info->win) ? retrieve_all_messages_cb : NULL,
1905 new_messages_arrived, info->win);
1910 g_object_unref (G_OBJECT (info->mail_op));
1911 if (info->account_name)
1912 g_free (info->account_name);
1914 g_object_unref (info->win);
1916 g_object_unref (info->account);
1917 g_slice_free (SendReceiveInfo, info);
1921 * This function performs the send & receive required actions. The
1922 * window is used to create the mail operation. Typically it should
1923 * always be the main window, but we pass it as argument in order to
1927 modest_ui_actions_do_send_receive (const gchar *account_name,
1928 gboolean force_connection,
1929 gboolean poke_status,
1930 gboolean interactive,
1933 gchar *acc_name = NULL;
1934 SendReceiveInfo *info;
1935 ModestTnyAccountStore *acc_store;
1937 /* If no account name was provided then get the current account, and if
1938 there is no current account then pick the default one: */
1939 if (!account_name) {
1941 acc_name = g_strdup (modest_window_get_active_account (win));
1943 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1945 g_printerr ("modest: cannot get default account\n");
1949 acc_name = g_strdup (account_name);
1952 acc_store = modest_runtime_get_account_store ();
1954 /* Create the info for the connect and perform */
1955 info = g_slice_new (SendReceiveInfo);
1956 info->account_name = acc_name;
1957 info->win = (win) ? g_object_ref (win) : NULL;
1958 info->poke_status = poke_status;
1959 info->interactive = interactive;
1960 info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1961 TNY_ACCOUNT_TYPE_STORE);
1962 /* We need to create the operation here, because otherwise it
1963 could happen that the queue emits the queue-empty signal
1964 while we're trying to connect the account */
1965 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1966 modest_ui_actions_disk_operations_error_handler,
1968 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
1970 /* Invoke the connect and perform */
1971 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
1972 force_connection, info->account,
1973 do_send_receive_performer, info);
1978 modest_ui_actions_do_cancel_send (const gchar *account_name,
1981 TnyTransportAccount *transport_account;
1982 TnySendQueue *send_queue = NULL;
1983 GError *error = NULL;
1985 /* Get transport account */
1987 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1988 (modest_runtime_get_account_store(),
1990 TNY_ACCOUNT_TYPE_TRANSPORT));
1991 if (!transport_account) {
1992 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1997 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1998 if (!TNY_IS_SEND_QUEUE(send_queue)) {
1999 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2000 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2001 "modest: could not find send queue for account\n");
2003 /* Cancel the current send */
2004 tny_account_cancel (TNY_ACCOUNT (transport_account));
2006 /* Suspend all pending messages */
2007 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2011 if (transport_account != NULL)
2012 g_object_unref (G_OBJECT (transport_account));
2016 modest_ui_actions_cancel_send_all (ModestWindow *win)
2018 GSList *account_names, *iter;
2020 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2023 iter = account_names;
2025 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2026 iter = g_slist_next (iter);
2029 modest_account_mgr_free_account_names (account_names);
2030 account_names = NULL;
2034 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2037 /* Check if accounts exist */
2038 gboolean accounts_exist =
2039 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2041 /* If not, allow the user to create an account before trying to send/receive. */
2042 if (!accounts_exist)
2043 modest_ui_actions_on_accounts (NULL, win);
2045 /* Cancel all sending operaitons */
2046 modest_ui_actions_cancel_send_all (win);
2050 * Refreshes all accounts. This function will be used by automatic
2054 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2055 gboolean force_connection,
2056 gboolean poke_status,
2057 gboolean interactive)
2059 GSList *account_names, *iter;
2061 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2064 iter = account_names;
2066 modest_ui_actions_do_send_receive ((const char*) iter->data,
2068 poke_status, interactive, win);
2069 iter = g_slist_next (iter);
2072 modest_account_mgr_free_account_names (account_names);
2073 account_names = NULL;
2077 * Handler of the click on Send&Receive button in the main toolbar
2080 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2082 /* Check if accounts exist */
2083 gboolean accounts_exist;
2086 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2088 /* If not, allow the user to create an account before trying to send/receive. */
2089 if (!accounts_exist)
2090 modest_ui_actions_on_accounts (NULL, win);
2092 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2093 if (MODEST_IS_MAIN_WINDOW (win)) {
2094 GtkWidget *folder_view;
2095 TnyFolderStore *folder_store;
2098 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2099 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2103 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2106 g_object_unref (folder_store);
2109 /* Refresh the active account. Force the connection if needed
2110 and poke the status of all folders */
2111 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2116 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2119 GtkWidget *header_view;
2121 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2123 header_view = modest_main_window_get_child_widget (main_window,
2124 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2128 conf = modest_runtime_get_conf ();
2130 /* what is saved/restored is depending on the style; thus; we save with
2131 * old style, then update the style, and restore for this new style
2133 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2135 if (modest_header_view_get_style
2136 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2137 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2138 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2140 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2141 MODEST_HEADER_VIEW_STYLE_DETAILS);
2143 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2144 MODEST_CONF_HEADER_VIEW_KEY);
2149 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2151 ModestMainWindow *main_window)
2153 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2154 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2156 /* in the case the folder is empty, show the empty folder message and focus
2158 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2159 if (modest_header_view_is_empty (header_view)) {
2160 TnyFolder *folder = modest_header_view_get_folder (header_view);
2161 GtkWidget *folder_view =
2162 modest_main_window_get_child_widget (main_window,
2163 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2165 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2166 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2170 /* If no header has been selected then exit */
2175 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2176 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2178 /* Update toolbar dimming state */
2179 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2180 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2184 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2186 ModestMainWindow *main_window)
2190 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2195 if (modest_header_view_count_selected_headers (header_view) > 1) {
2196 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2200 /* we check for low-mem; in that case, show a warning, and don't allow
2201 * activating headers
2203 if (modest_platform_check_memory_low (MODEST_WINDOW(main_window)))
2207 /* headers = tny_simple_list_new (); */
2208 /* tny_list_prepend (headers, G_OBJECT (header)); */
2209 headers = modest_header_view_get_selected_headers (header_view);
2211 open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2213 g_object_unref (headers);
2217 set_active_account_from_tny_account (TnyAccount *account,
2218 ModestWindow *window)
2220 const gchar *server_acc_name = tny_account_get_id (account);
2222 /* We need the TnyAccount provided by the
2223 account store because that is the one that
2224 knows the name of the Modest account */
2225 TnyAccount *modest_server_account = modest_server_account =
2226 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2227 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2229 if (!modest_server_account) {
2230 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2234 /* Update active account, but only if it's not a pseudo-account */
2235 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2236 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2237 const gchar *modest_acc_name =
2238 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2239 if (modest_acc_name)
2240 modest_window_set_active_account (window, modest_acc_name);
2243 g_object_unref (modest_server_account);
2248 folder_refreshed_cb (ModestMailOperation *mail_op,
2252 ModestMainWindow *win = NULL;
2253 GtkWidget *header_view;
2255 g_return_if_fail (TNY_IS_FOLDER (folder));
2257 win = MODEST_MAIN_WINDOW (user_data);
2259 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2262 TnyFolder *current_folder;
2264 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2265 if (current_folder != NULL && folder != current_folder) {
2266 g_object_unref (current_folder);
2268 } else if (current_folder)
2269 g_object_unref (current_folder);
2272 /* Check if folder is empty and set headers view contents style */
2273 if (tny_folder_get_all_count (folder) == 0)
2274 modest_main_window_set_contents_style (win,
2275 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2280 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2281 TnyFolderStore *folder_store,
2283 ModestMainWindow *main_window)
2286 GtkWidget *header_view;
2288 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2290 header_view = modest_main_window_get_child_widget(main_window,
2291 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2295 conf = modest_runtime_get_conf ();
2297 if (TNY_IS_ACCOUNT (folder_store)) {
2299 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2301 /* Show account details */
2302 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2305 if (TNY_IS_FOLDER (folder_store) && selected) {
2307 /* Update the active account */
2308 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2310 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2311 g_object_unref (account);
2315 /* Set the header style by default, it could
2316 be changed later by the refresh callback to
2318 modest_main_window_set_contents_style (main_window,
2319 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2321 /* Set folder on header view. This function
2322 will call tny_folder_refresh_async so we
2323 pass a callback that will be called when
2324 finished. We use that callback to set the
2325 empty view if there are no messages */
2326 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2327 TNY_FOLDER (folder_store),
2328 folder_refreshed_cb,
2331 /* Restore configuration. We need to do this
2332 *after* the set_folder because the widget
2333 memory asks the header view about its
2335 modest_widget_memory_restore (modest_runtime_get_conf (),
2336 G_OBJECT(header_view),
2337 MODEST_CONF_HEADER_VIEW_KEY);
2339 /* No need to save the header view
2340 configuration for Maemo because it only
2341 saves the sorting stuff and that it's
2342 already being done by the sort
2343 dialog. Remove it when the GNOME version
2344 has the same behaviour */
2345 #ifdef MODEST_PLATFORM_GNOME
2346 if (modest_main_window_get_contents_style (main_window) ==
2347 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2348 modest_widget_memory_save (conf, G_OBJECT (header_view),
2349 MODEST_CONF_HEADER_VIEW_KEY);
2351 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2355 /* Update dimming state */
2356 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2357 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2361 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2368 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2370 online = tny_device_is_online (modest_runtime_get_device());
2373 /* already online -- the item is simply not there... */
2374 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2376 GTK_MESSAGE_WARNING,
2378 _("The %s you selected cannot be found"),
2380 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2381 gtk_dialog_run (GTK_DIALOG(dialog));
2383 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2386 _("mcen_bd_dialog_cancel"),
2387 GTK_RESPONSE_REJECT,
2388 _("mcen_bd_dialog_ok"),
2389 GTK_RESPONSE_ACCEPT,
2391 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2392 "Do you want to get online?"), item);
2393 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2394 gtk_label_new (txt), FALSE, FALSE, 0);
2395 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2398 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2399 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2400 /* TODO: Comment about why is this commented out: */
2401 /* modest_platform_connect_and_wait (); */
2404 gtk_widget_destroy (dialog);
2408 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2411 /* g_message ("%s %s", __FUNCTION__, link); */
2416 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2419 modest_platform_activate_uri (link);
2423 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2426 modest_platform_show_uri_popup (link);
2430 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2433 /* we check for low-mem; in that case, show a warning, and don't allow
2434 * viewing attachments
2436 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
2439 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2443 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2444 const gchar *address,
2447 /* g_message ("%s %s", __FUNCTION__, address); */
2451 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2452 TnyMsg *saved_draft,
2455 ModestMsgEditWindow *edit_window;
2456 ModestMainWindow *win;
2458 /* FIXME. Make the header view sensitive again. This is a
2459 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2461 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2462 modest_runtime_get_window_mgr(), FALSE));
2464 GtkWidget *hdrview = modest_main_window_get_child_widget(
2465 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2466 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2469 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2471 /* Set draft is there was no error */
2472 if (!modest_mail_operation_get_error (mail_op))
2473 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2475 g_object_unref(edit_window);
2479 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2481 TnyTransportAccount *transport_account;
2482 ModestMailOperation *mail_operation;
2484 gchar *account_name, *from;
2485 ModestAccountMgr *account_mgr;
2486 /* char *info_text; */
2487 gboolean had_error = FALSE;
2488 guint64 available_disk, expected_size;
2491 ModestMainWindow *win;
2493 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2495 data = modest_msg_edit_window_get_msg_data (edit_window);
2498 available_disk = modest_folder_available_space (NULL);
2499 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2500 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2505 if ((available_disk != -1) && expected_size > available_disk) {
2506 modest_msg_edit_window_free_msg_data (edit_window, data);
2508 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2513 * djcb: if we're in low-memory state, we only allow for
2514 * saving messages smaller than
2515 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2516 * should still allow for sending anything critical...
2518 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2520 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2521 modest_msg_edit_window_free_msg_data (edit_window, data);
2527 * djcb: we also make sure that the attachments are smaller than the max size
2528 * this is for the case where we'd try to forward a message with attachments
2529 * bigger than our max allowed size, or sending an message from drafts which
2530 * somehow got past our checks when attaching.
2532 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2533 modest_platform_run_information_dialog (
2534 GTK_WINDOW(edit_window),
2535 dgettext("ke-recv","memr_ib_operation_disabled"),
2537 modest_msg_edit_window_free_msg_data (edit_window, data);
2541 account_name = g_strdup (data->account_name);
2542 account_mgr = modest_runtime_get_account_mgr();
2544 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2546 account_name = modest_account_mgr_get_default_account (account_mgr);
2547 if (!account_name) {
2548 g_printerr ("modest: no account found\n");
2549 modest_msg_edit_window_free_msg_data (edit_window, data);
2553 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2554 account_name = g_strdup (data->account_name);
2558 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2559 (modest_runtime_get_account_store(),
2561 TNY_ACCOUNT_TYPE_TRANSPORT));
2562 if (!transport_account) {
2563 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2564 g_free (account_name);
2565 modest_msg_edit_window_free_msg_data (edit_window, data);
2568 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2570 /* Create the mail operation */
2571 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2573 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2575 modest_mail_operation_save_to_drafts (mail_operation,
2587 data->priority_flags,
2588 on_save_to_drafts_cb,
2589 g_object_ref(edit_window));
2591 /* Use the main window as the parent of the banner, if the
2592 main window does not exist it won't be shown, if the parent
2593 window exists then it's properly shown. We don't use the
2594 editor window because it could be closed (save to drafts
2595 could happen after closing the window */
2596 win = (ModestMainWindow *)
2597 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2599 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2600 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2603 modest_msg_edit_window_set_modified (edit_window, FALSE);
2607 g_free (account_name);
2608 g_object_unref (G_OBJECT (transport_account));
2609 g_object_unref (G_OBJECT (mail_operation));
2611 modest_msg_edit_window_free_msg_data (edit_window, data);
2614 * If the drafts folder is selected then make the header view
2615 * insensitive while the message is being saved to drafts
2616 * (it'll be sensitive again in on_save_to_drafts_cb()). This
2617 * is not very clean but it avoids letting the drafts folder
2618 * in an inconsistent state: the user could edit the message
2619 * being saved and undesirable things would happen.
2620 * In the average case the user won't notice anything at
2621 * all. In the worst case (the user is editing a really big
2622 * file from Drafts) the header view will be insensitive
2623 * during the saving process (10 or 20 seconds, depending on
2624 * the message). Anyway this is just a quick workaround: once
2625 * we find a better solution it should be removed
2626 * See NB#65125 (commend #18) for details.
2628 if (!had_error && win != NULL) {
2629 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2630 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2632 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2634 if (modest_tny_folder_is_local_folder(folder)) {
2635 TnyFolderType folder_type;
2636 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2637 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2638 GtkWidget *hdrview = modest_main_window_get_child_widget(
2639 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2640 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2644 if (folder != NULL) g_object_unref(folder);
2651 /* For instance, when clicking the Send toolbar button when editing a message: */
2653 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2655 TnyTransportAccount *transport_account = NULL;
2656 gboolean had_error = FALSE;
2657 guint64 available_disk, expected_size;
2661 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2663 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2666 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2669 available_disk = modest_folder_available_space (NULL);
2670 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2671 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2676 if ((available_disk != -1) && expected_size > available_disk) {
2677 modest_msg_edit_window_free_msg_data (edit_window, data);
2679 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2685 * djcb: if we're in low-memory state, we only allow for sending messages
2686 * smaller than MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h)
2687 * this should still allow for sending anything critical...
2689 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2690 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2691 modest_msg_edit_window_free_msg_data (edit_window, data);
2697 * djcb: we also make sure that the attachments are smaller than the max size
2698 * this is for the case where we'd try to forward a message with attachments
2699 * bigger than our max allowed size, or sending an message from drafts which
2700 * somehow got past our checks when attaching.
2702 if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2703 modest_platform_run_information_dialog (
2704 GTK_WINDOW(edit_window),
2705 dgettext("ke-recv","memr_ib_operation_disabled"),
2707 modest_msg_edit_window_free_msg_data (edit_window, data);
2711 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2712 gchar *account_name = g_strdup (data->account_name);
2714 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2717 account_name = modest_account_mgr_get_default_account (account_mgr);
2719 if (!account_name) {
2720 modest_msg_edit_window_free_msg_data (edit_window, data);
2721 /* Run account setup wizard */
2722 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2727 /* Get the currently-active transport account for this modest account: */
2728 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2729 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2730 (modest_runtime_get_account_store(),
2731 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2734 if (!transport_account) {
2735 modest_msg_edit_window_free_msg_data (edit_window, data);
2736 /* Run account setup wizard */
2737 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2741 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2743 /* Create the mail operation */
2744 ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2745 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2747 modest_mail_operation_send_new_mail (mail_operation,
2759 data->priority_flags);
2761 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2762 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2765 if (modest_mail_operation_get_error (mail_operation) != NULL) {
2766 const GError *error = modest_mail_operation_get_error (mail_operation);
2767 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2768 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2769 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2776 g_free (account_name);
2777 g_object_unref (G_OBJECT (transport_account));
2778 g_object_unref (G_OBJECT (mail_operation));
2780 modest_msg_edit_window_free_msg_data (edit_window, data);
2783 modest_msg_edit_window_set_sent (edit_window, TRUE);
2785 /* Save settings and close the window: */
2786 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2793 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2794 ModestMsgEditWindow *window)
2796 ModestMsgEditFormatState *format_state = NULL;
2798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2799 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2801 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2804 format_state = modest_msg_edit_window_get_format_state (window);
2805 g_return_if_fail (format_state != NULL);
2807 format_state->bold = gtk_toggle_action_get_active (action);
2808 modest_msg_edit_window_set_format_state (window, format_state);
2809 g_free (format_state);
2814 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2815 ModestMsgEditWindow *window)
2817 ModestMsgEditFormatState *format_state = NULL;
2819 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2820 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2822 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2825 format_state = modest_msg_edit_window_get_format_state (window);
2826 g_return_if_fail (format_state != NULL);
2828 format_state->italics = gtk_toggle_action_get_active (action);
2829 modest_msg_edit_window_set_format_state (window, format_state);
2830 g_free (format_state);
2835 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2836 ModestMsgEditWindow *window)
2838 ModestMsgEditFormatState *format_state = NULL;
2840 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2841 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2843 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2846 format_state = modest_msg_edit_window_get_format_state (window);
2847 g_return_if_fail (format_state != NULL);
2849 format_state->bullet = gtk_toggle_action_get_active (action);
2850 modest_msg_edit_window_set_format_state (window, format_state);
2851 g_free (format_state);
2856 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2857 GtkRadioAction *selected,
2858 ModestMsgEditWindow *window)
2860 ModestMsgEditFormatState *format_state = NULL;
2861 GtkJustification value;
2863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2865 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2868 value = gtk_radio_action_get_current_value (selected);
2870 format_state = modest_msg_edit_window_get_format_state (window);
2871 g_return_if_fail (format_state != NULL);
2873 format_state->justification = value;
2874 modest_msg_edit_window_set_format_state (window, format_state);
2875 g_free (format_state);
2879 modest_ui_actions_on_select_editor_color (GtkAction *action,
2880 ModestMsgEditWindow *window)
2882 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2883 g_return_if_fail (GTK_IS_ACTION (action));
2885 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2888 modest_msg_edit_window_select_color (window);
2892 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2893 ModestMsgEditWindow *window)
2895 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2896 g_return_if_fail (GTK_IS_ACTION (action));
2898 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2901 modest_msg_edit_window_select_background_color (window);
2905 modest_ui_actions_on_insert_image (GtkAction *action,
2906 ModestMsgEditWindow *window)
2908 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2909 g_return_if_fail (GTK_IS_ACTION (action));
2912 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2915 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2918 modest_msg_edit_window_insert_image (window);
2922 modest_ui_actions_on_attach_file (GtkAction *action,
2923 ModestMsgEditWindow *window)
2925 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2926 g_return_if_fail (GTK_IS_ACTION (action));
2928 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2931 modest_msg_edit_window_offer_attach_file (window);
2935 modest_ui_actions_on_remove_attachments (GtkAction *action,
2936 ModestMsgEditWindow *window)
2938 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2939 g_return_if_fail (GTK_IS_ACTION (action));
2941 modest_msg_edit_window_remove_attachments (window, NULL);
2945 do_create_folder_cb (ModestMailOperation *mail_op,
2946 TnyFolderStore *parent_folder,
2947 TnyFolder *new_folder,
2950 gchar *suggested_name = (gchar *) user_data;
2951 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2953 if (modest_mail_operation_get_error (mail_op)) {
2955 /* Show an error. If there was some problem writing to
2956 disk, show it, otherwise show the generic folder
2957 create error. We do it here and not in an error
2958 handler because the call to do_create_folder will
2959 stop the main loop in a gtk_dialog_run and then,
2960 the message won't be shown until that dialog is
2962 modest_ui_actions_disk_operations_error_handler (mail_op,
2963 _("mail_in_ui_folder_create_error"));
2965 /* Try again. Do *NOT* show any error because the mail
2966 operations system will do it for us because we
2967 created the mail_op with new_with_error_handler */
2968 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2970 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2971 * FIXME: any other? */
2972 GtkWidget *folder_view;
2974 if (MODEST_IS_MAIN_WINDOW(source_win))
2976 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2977 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2980 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2982 /* Select the newly created folder. It could happen
2983 that the widget is no longer there (i.e. the window
2984 has been destroyed, so we need to check this */
2986 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2988 g_object_unref (new_folder);
2990 /* Free. Note that the first time it'll be NULL so noop */
2991 g_free (suggested_name);
2992 g_object_unref (source_win);
2996 do_create_folder (GtkWindow *parent_window,
2997 TnyFolderStore *parent_folder,
2998 const gchar *suggested_name)
3001 gchar *folder_name = NULL;
3003 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3005 (gchar *) suggested_name,
3008 if (result == GTK_RESPONSE_ACCEPT) {
3009 ModestMailOperation *mail_op;
3011 mail_op = modest_mail_operation_new ((GObject *) parent_window);
3012 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3014 modest_mail_operation_create_folder (mail_op,
3016 (const gchar *) folder_name,
3017 do_create_folder_cb,
3019 g_object_unref (mail_op);
3024 create_folder_performer (gboolean canceled,
3026 GtkWindow *parent_window,
3027 TnyAccount *account,
3030 TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3032 if (canceled || err) {
3033 /* In memory full conditions we could get this error here */
3034 if (err && is_memory_full_error (err)) {
3035 modest_platform_information_banner ((GtkWidget *) parent_window,
3036 NULL, dgettext("ke-recv",
3037 "cerm_device_memory_full"));
3042 /* Run the new folder dialog */
3043 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3046 g_object_unref (parent_folder);
3050 modest_ui_actions_create_folder(GtkWidget *parent_window,
3051 GtkWidget *folder_view)
3053 TnyFolderStore *parent_folder;
3055 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3057 if (parent_folder) {
3058 /* The parent folder will be freed in the callback */
3059 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3062 create_folder_performer,
3068 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3070 GtkWidget *folder_view;
3072 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3074 folder_view = modest_main_window_get_child_widget (main_window,
3075 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3079 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3083 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3086 const GError *error = NULL;
3087 const gchar *message = NULL;
3089 /* Get error message */
3090 error = modest_mail_operation_get_error (mail_op);
3092 g_return_if_reached ();
3094 switch (error->code) {
3095 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
3096 message = _CS("ckdg_ib_folder_already_exists");
3099 message = _("emev_ib_ui_imap_unable_to_rename");
3102 /* We don't set a parent for the dialog because the dialog
3103 will be destroyed so the banner won't appear */
3104 modest_platform_information_banner (NULL, NULL, message);
3108 TnyFolderStore *folder;
3113 on_rename_folder_cb (ModestMailOperation *mail_op,
3114 TnyFolder *new_folder,
3117 ModestFolderView *folder_view;
3119 /* If the window was closed when renaming a folder this could
3121 if (MODEST_IS_FOLDER_VIEW (user_data))
3124 folder_view = MODEST_FOLDER_VIEW (user_data);
3125 /* Note that if the rename fails new_folder will be NULL */
3127 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3129 modest_folder_view_select_first_inbox_or_local (folder_view);
3134 on_rename_folder_performer (gboolean canceled,
3136 GtkWindow *parent_window,
3137 TnyAccount *account,
3140 ModestMailOperation *mail_op = NULL;
3141 GtkTreeSelection *sel = NULL;
3142 GtkWidget *folder_view = NULL;
3143 RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3145 if (canceled || err) {
3146 /* In memory full conditions we could get this error here */
3147 if (err && is_memory_full_error (err)) {
3148 modest_platform_information_banner ((GtkWidget *) parent_window,
3149 NULL, dgettext("ke-recv",
3150 "cerm_device_memory_full"));
3152 } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3154 folder_view = modest_main_window_get_child_widget (
3155 MODEST_MAIN_WINDOW (parent_window),
3156 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3159 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3160 modest_ui_actions_rename_folder_error_handler,
3161 parent_window, NULL);
3163 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3166 /* Clear the headers view */
3167 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3168 gtk_tree_selection_unselect_all (sel);
3170 /* Actually rename the folder */
3171 modest_mail_operation_rename_folder (mail_op,
3172 TNY_FOLDER (data->folder),
3173 (const gchar *) (data->new_name),
3174 on_rename_folder_cb,
3176 g_object_unref (mail_op);
3179 g_free (data->new_name);
3184 modest_ui_actions_on_rename_folder (GtkAction *action,
3185 ModestMainWindow *main_window)
3187 TnyFolderStore *folder;
3188 GtkWidget *folder_view;
3189 GtkWidget *header_view;
3191 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3193 folder_view = modest_main_window_get_child_widget (main_window,
3194 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3198 header_view = modest_main_window_get_child_widget (main_window,
3199 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3204 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3209 if (TNY_IS_FOLDER (folder)) {
3212 const gchar *current_name;
3213 TnyFolderStore *parent;
3214 gboolean do_rename = TRUE;
3216 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3217 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3218 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
3219 parent, current_name,
3221 g_object_unref (parent);
3223 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3226 RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3227 rename_folder_data->folder = folder;
3228 rename_folder_data->new_name = folder_name;
3229 modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3230 folder, on_rename_folder_performer, rename_folder_data);
3233 g_object_unref (folder);
3237 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3240 GObject *win = modest_mail_operation_get_source (mail_op);
3242 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3243 _("mail_in_ui_folder_delete_error"),
3245 g_object_unref (win);
3249 TnyFolderStore *folder;
3250 gboolean move_to_trash;
3254 on_delete_folder_cb (gboolean canceled,
3256 GtkWindow *parent_window,
3257 TnyAccount *account,
3260 DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3261 GtkWidget *folder_view;
3262 ModestMailOperation *mail_op;
3263 GtkTreeSelection *sel;
3265 if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3266 g_object_unref (G_OBJECT (info->folder));
3271 folder_view = modest_main_window_get_child_widget (
3272 MODEST_MAIN_WINDOW (parent_window),
3273 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3275 /* Unselect the folder before deleting it to free the headers */
3276 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3277 gtk_tree_selection_unselect_all (sel);
3279 /* Create the mail operation */
3281 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3282 modest_ui_actions_delete_folder_error_handler,
3285 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3287 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3289 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3291 g_object_unref (G_OBJECT (mail_op));
3292 g_object_unref (G_OBJECT (info->folder));
3297 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3299 TnyFolderStore *folder;
3300 GtkWidget *folder_view;
3304 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3306 folder_view = modest_main_window_get_child_widget (main_window,
3307 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3311 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3313 /* Show an error if it's an account */
3314 if (!TNY_IS_FOLDER (folder)) {
3315 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3316 _("mail_in_ui_folder_delete_error"),
3318 g_object_unref (G_OBJECT (folder));
3323 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
3324 tny_folder_get_name (TNY_FOLDER (folder)));
3325 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3326 (const gchar *) message);
3329 if (response == GTK_RESPONSE_OK) {
3330 DeleteFolderInfo *info;
3331 info = g_new0(DeleteFolderInfo, 1);
3332 info->folder = folder;
3333 info->move_to_trash = move_to_trash;
3334 g_object_ref (G_OBJECT (info->folder));
3335 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3336 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window),
3338 TNY_FOLDER_STORE (account),
3339 on_delete_folder_cb, info);
3340 g_object_unref (account);
3342 g_object_unref (G_OBJECT (folder));
3346 modest_ui_actions_on_delete_folder (GtkAction *action,
3347 ModestMainWindow *main_window)
3349 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3351 delete_folder (main_window, FALSE);
3355 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3357 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3359 delete_folder (main_window, TRUE);
3364 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3365 const gchar* server_account_name,
3370 ModestMainWindow *main_window)
3372 g_return_if_fail(server_account_name);
3373 gboolean completed = FALSE;
3375 /* Initalize output parameters: */
3382 #ifdef MODEST_PLATFORM_MAEMO
3383 /* Maemo uses a different (awkward) button order,
3384 * It should probably just use gtk_alternative_dialog_button_order ().
3386 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3389 _("mcen_bd_dialog_ok"),
3390 GTK_RESPONSE_ACCEPT,
3391 _("mcen_bd_dialog_cancel"),
3392 GTK_RESPONSE_REJECT,
3395 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3399 GTK_RESPONSE_REJECT,
3401 GTK_RESPONSE_ACCEPT,
3403 #endif /* MODEST_PLATFORM_MAEMO */
3405 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3407 gchar *server_name = modest_account_mgr_get_server_account_hostname (
3408 modest_runtime_get_account_mgr(), server_account_name);
3409 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3410 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3416 /* This causes a warning because the logical ID has no %s in it,
3417 * though the translation does, but there is not much we can do about that: */
3418 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3419 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3422 g_free (server_name);
3426 gchar *initial_username = modest_account_mgr_get_server_account_username (
3427 modest_runtime_get_account_mgr(), server_account_name);
3429 GtkWidget *entry_username = gtk_entry_new ();
3430 if (initial_username)
3431 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3432 /* Dim this if a connection has ever succeeded with this username,
3433 * as per the UI spec: */
3434 const gboolean username_known =
3435 modest_account_mgr_get_server_account_username_has_succeeded(
3436 modest_runtime_get_account_mgr(), server_account_name);
3437 gtk_widget_set_sensitive (entry_username, !username_known);
3439 #ifdef MODEST_PLATFORM_MAEMO
3440 /* Auto-capitalization is the default, so let's turn it off: */
3441 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3443 /* Create a size group to be used by all captions.
3444 * Note that HildonCaption does not create a default size group if we do not specify one.
3445 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3446 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3448 GtkWidget *caption = hildon_caption_new (sizegroup,
3449 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3450 gtk_widget_show (entry_username);
3451 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3452 FALSE, FALSE, MODEST_MARGIN_HALF);
3453 gtk_widget_show (caption);
3455 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3457 #endif /* MODEST_PLATFORM_MAEMO */
3460 GtkWidget *entry_password = gtk_entry_new ();
3461 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3462 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3464 #ifdef MODEST_PLATFORM_MAEMO
3465 /* Auto-capitalization is the default, so let's turn it off: */
3466 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3467 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3469 caption = hildon_caption_new (sizegroup,
3470 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3471 gtk_widget_show (entry_password);
3472 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3473 FALSE, FALSE, MODEST_MARGIN_HALF);
3474 gtk_widget_show (caption);
3475 g_object_unref (sizegroup);
3477 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3479 #endif /* MODEST_PLATFORM_MAEMO */
3481 if (initial_username != NULL)
3482 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3484 /* This is not in the Maemo UI spec:
3485 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3486 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3490 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3492 while (!completed) {
3494 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3496 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3498 /* Note that an empty field becomes the "" string */
3499 if (*username && strlen (*username) > 0) {
3500 modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3501 server_account_name,
3505 const gboolean username_was_changed =
3506 (strcmp (*username, initial_username) != 0);
3507 if (username_was_changed) {
3508 g_warning ("%s: tinymail does not yet support changing the "
3509 "username in the get_password() callback.\n", __FUNCTION__);
3513 modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3514 _("mcen_ib_username_pw_incorrect"));
3520 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3522 /* We do not save the password in the configuration,
3523 * because this function is only called for passwords that should
3524 * not be remembered:
3525 modest_server_account_set_password (
3526 modest_runtime_get_account_mgr(), server_account_name,
3533 /* Set parent to NULL or the banner will disappear with its parent dialog */
3534 modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3545 /* This is not in the Maemo UI spec:
3546 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3552 gtk_widget_destroy (dialog);
3554 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3558 modest_ui_actions_on_cut (GtkAction *action,
3559 ModestWindow *window)
3561 GtkWidget *focused_widget;
3562 GtkClipboard *clipboard;
3564 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3565 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3566 if (GTK_IS_EDITABLE (focused_widget)) {
3567 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3568 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3569 gtk_clipboard_store (clipboard);
3570 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3571 GtkTextBuffer *buffer;
3573 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3574 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3575 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3576 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3577 gtk_clipboard_store (clipboard);
3579 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3580 TnyList *header_list = modest_header_view_get_selected_headers (
3581 MODEST_HEADER_VIEW (focused_widget));
3582 gboolean continue_download = FALSE;
3583 gint num_of_unc_msgs;
3585 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3587 if (num_of_unc_msgs) {
3588 TnyAccount *account = get_account_from_header_list (header_list);
3590 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3591 g_object_unref (account);
3595 if (num_of_unc_msgs == 0 || continue_download) {
3596 /* modest_platform_information_banner (
3597 NULL, NULL, _CS("mcen_ib_getting_items"));*/
3598 modest_header_view_cut_selection (
3599 MODEST_HEADER_VIEW (focused_widget));
3602 g_object_unref (header_list);
3603 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3604 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3609 modest_ui_actions_on_copy (GtkAction *action,
3610 ModestWindow *window)
3612 GtkClipboard *clipboard;
3613 GtkWidget *focused_widget;
3614 gboolean copied = TRUE;
3616 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3617 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3619 if (GTK_IS_LABEL (focused_widget)) {
3621 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3622 gtk_clipboard_set_text (clipboard, selection, -1);
3624 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3625 gtk_clipboard_store (clipboard);
3626 } else if (GTK_IS_EDITABLE (focused_widget)) {
3627 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3628 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3629 gtk_clipboard_store (clipboard);
3630 } else if (GTK_IS_HTML (focused_widget)) {
3631 gtk_html_copy (GTK_HTML (focused_widget));
3632 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3633 gtk_clipboard_store (clipboard);
3634 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3635 GtkTextBuffer *buffer;
3636 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3637 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3638 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3639 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3640 gtk_clipboard_store (clipboard);
3642 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3643 TnyList *header_list = modest_header_view_get_selected_headers (
3644 MODEST_HEADER_VIEW (focused_widget));
3645 gboolean continue_download = FALSE;
3646 gint num_of_unc_msgs;
3648 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3650 if (num_of_unc_msgs) {
3651 TnyAccount *account = get_account_from_header_list (header_list);
3653 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3654 g_object_unref (account);
3658 if (num_of_unc_msgs == 0 || continue_download) {
3659 modest_platform_information_banner (
3660 NULL, NULL, _CS("mcen_ib_getting_items"));
3661 modest_header_view_copy_selection (
3662 MODEST_HEADER_VIEW (focused_widget));
3666 g_object_unref (header_list);
3668 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3669 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3672 /* Show information banner if there was a copy to clipboard */
3674 modest_platform_information_banner (
3675 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3679 modest_ui_actions_on_undo (GtkAction *action,
3680 ModestWindow *window)
3682 ModestEmailClipboard *clipboard = NULL;
3684 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3685 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3686 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3687 /* Clear clipboard source */
3688 clipboard = modest_runtime_get_email_clipboard ();
3689 modest_email_clipboard_clear (clipboard);
3692 g_return_if_reached ();
3697 modest_ui_actions_on_redo (GtkAction *action,
3698 ModestWindow *window)
3700 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3701 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3704 g_return_if_reached ();
3710 destroy_information_note (ModestMailOperation *mail_op,
3713 /* destroy information note */
3714 gtk_widget_destroy (GTK_WIDGET(user_data));
3718 destroy_folder_information_note (ModestMailOperation *mail_op,
3719 TnyFolder *new_folder,
3722 /* destroy information note */
3723 gtk_widget_destroy (GTK_WIDGET(user_data));
3728 paste_as_attachment_free (gpointer data)
3730 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3732 gtk_widget_destroy (helper->banner);
3733 g_object_unref (helper->banner);
3738 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3743 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3744 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3749 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3754 modest_ui_actions_on_paste (GtkAction *action,
3755 ModestWindow *window)
3757 GtkWidget *focused_widget = NULL;
3758 GtkWidget *inf_note = NULL;
3759 ModestMailOperation *mail_op = NULL;
3761 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3762 if (GTK_IS_EDITABLE (focused_widget)) {
3763 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3764 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3765 ModestEmailClipboard *e_clipboard = NULL;
3766 e_clipboard = modest_runtime_get_email_clipboard ();
3767 if (modest_email_clipboard_cleared (e_clipboard)) {
3768 GtkTextBuffer *buffer;
3769 GtkClipboard *clipboard;
3771 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3772 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3773 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3774 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3775 ModestMailOperation *mail_op;
3776 TnyFolder *src_folder;
3779 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3780 helper->window = MODEST_MSG_EDIT_WINDOW (window);
3781 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3782 _CS("ckct_nw_pasting"));
3783 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3784 mail_op = modest_mail_operation_new (G_OBJECT (window));
3785 if (helper->banner != NULL) {
3786 g_object_ref (G_OBJECT (helper->banner));
3787 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3788 gtk_widget_show (GTK_WIDGET (helper->banner));
3792 modest_mail_operation_get_msgs_full (mail_op,
3794 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3796 paste_as_attachment_free);
3799 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3800 ModestEmailClipboard *clipboard = NULL;
3801 TnyFolder *src_folder = NULL;
3802 TnyFolderStore *folder_store = NULL;
3803 TnyList *data = NULL;
3804 gboolean delete = FALSE;
3806 /* Check clipboard source */
3807 clipboard = modest_runtime_get_email_clipboard ();
3808 if (modest_email_clipboard_cleared (clipboard))
3811 /* Get elements to paste */
3812 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3814 /* Create a new mail operation */
3815 mail_op = modest_mail_operation_new (G_OBJECT(window));
3817 /* Get destination folder */
3818 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3820 /* transfer messages */
3824 /* Ask for user confirmation */
3826 modest_ui_actions_msgs_move_to_confirmation (window,
3827 TNY_FOLDER (folder_store),
3831 if (response == GTK_RESPONSE_OK) {
3832 /* Launch notification */
3833 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3834 _CS("ckct_nw_pasting"));
3835 if (inf_note != NULL) {
3836 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3837 gtk_widget_show (GTK_WIDGET(inf_note));
3840 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3841 modest_mail_operation_xfer_msgs (mail_op,
3843 TNY_FOLDER (folder_store),
3845 destroy_information_note,
3848 g_object_unref (mail_op);
3851 } else if (src_folder != NULL) {
3852 /* Launch notification */
3853 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3854 _CS("ckct_nw_pasting"));
3855 if (inf_note != NULL) {
3856 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3857 gtk_widget_show (GTK_WIDGET(inf_note));
3860 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3861 modest_mail_operation_xfer_folder (mail_op,
3865 destroy_folder_information_note,
3871 g_object_unref (data);
3872 if (src_folder != NULL)
3873 g_object_unref (src_folder);
3874 if (folder_store != NULL)
3875 g_object_unref (folder_store);
3881 modest_ui_actions_on_select_all (GtkAction *action,
3882 ModestWindow *window)
3884 GtkWidget *focused_widget;
3886 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3887 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3888 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3889 } else if (GTK_IS_LABEL (focused_widget)) {
3890 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3891 } else if (GTK_IS_EDITABLE (focused_widget)) {
3892 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3893 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3894 GtkTextBuffer *buffer;
3895 GtkTextIter start, end;
3897 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3898 gtk_text_buffer_get_start_iter (buffer, &start);
3899 gtk_text_buffer_get_end_iter (buffer, &end);
3900 gtk_text_buffer_select_range (buffer, &start, &end);
3901 } else if (GTK_IS_HTML (focused_widget)) {
3902 gtk_html_select_all (GTK_HTML (focused_widget));
3903 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3904 GtkWidget *header_view = focused_widget;
3905 GtkTreeSelection *selection = NULL;
3907 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3908 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3909 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3912 /* Disable window dimming management */
3913 modest_window_disable_dimming (MODEST_WINDOW(window));
3915 /* Select all messages */
3916 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3917 gtk_tree_selection_select_all (selection);
3919 /* Set focuse on header view */
3920 gtk_widget_grab_focus (header_view);
3923 /* Enable window dimming management */
3924 modest_window_enable_dimming (MODEST_WINDOW(window));
3925 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3931 modest_ui_actions_on_mark_as_read (GtkAction *action,
3932 ModestWindow *window)
3934 g_return_if_fail (MODEST_IS_WINDOW(window));
3936 /* Mark each header as read */
3937 do_headers_action (window, headers_action_mark_as_read, NULL);
3941 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3942 ModestWindow *window)
3944 g_return_if_fail (MODEST_IS_WINDOW(window));
3946 /* Mark each header as read */
3947 do_headers_action (window, headers_action_mark_as_unread, NULL);
3951 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3952 GtkRadioAction *selected,
3953 ModestWindow *window)
3957 value = gtk_radio_action_get_current_value (selected);
3958 if (MODEST_IS_WINDOW (window)) {
3959 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3964 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3965 GtkRadioAction *selected,
3966 ModestWindow *window)
3968 TnyHeaderFlags flags;
3969 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3971 flags = gtk_radio_action_get_current_value (selected);
3972 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3976 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3977 GtkRadioAction *selected,
3978 ModestWindow *window)
3982 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3984 file_format = gtk_radio_action_get_current_value (selected);
3985 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3990 modest_ui_actions_on_zoom_plus (GtkAction *action,
3991 ModestWindow *window)
3993 g_return_if_fail (MODEST_IS_WINDOW (window));
3995 modest_window_zoom_plus (MODEST_WINDOW (window));
3999 modest_ui_actions_on_zoom_minus (GtkAction *action,
4000 ModestWindow *window)
4002 g_return_if_fail (MODEST_IS_WINDOW (window));
4004 modest_window_zoom_minus (MODEST_WINDOW (window));
4008 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
4009 ModestWindow *window)
4011 ModestWindowMgr *mgr;
4012 gboolean fullscreen, active;
4013 g_return_if_fail (MODEST_IS_WINDOW (window));
4015 mgr = modest_runtime_get_window_mgr ();
4017 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4018 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4020 if (active != fullscreen) {
4021 modest_window_mgr_set_fullscreen_mode (mgr, active);
4022 gtk_window_present (GTK_WINDOW (window));
4027 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4028 ModestWindow *window)
4030 ModestWindowMgr *mgr;
4031 gboolean fullscreen;
4033 g_return_if_fail (MODEST_IS_WINDOW (window));
4035 mgr = modest_runtime_get_window_mgr ();
4036 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4037 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4039 gtk_window_present (GTK_WINDOW (window));
4043 * Used by modest_ui_actions_on_details to call do_headers_action
4046 headers_action_show_details (TnyHeader *header,
4047 ModestWindow *window,
4054 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4057 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4058 gtk_widget_show_all (dialog);
4059 gtk_dialog_run (GTK_DIALOG (dialog));
4061 gtk_widget_destroy (dialog);
4065 * Show the folder details in a ModestDetailsDialog widget
4068 show_folder_details (TnyFolder *folder,
4074 dialog = modest_details_dialog_new_with_folder (window, folder);
4077 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4078 gtk_widget_show_all (dialog);
4079 gtk_dialog_run (GTK_DIALOG (dialog));
4081 gtk_widget_destroy (dialog);
4085 * Show the header details in a ModestDetailsDialog widget
4088 modest_ui_actions_on_details (GtkAction *action,
4091 TnyList * headers_list;
4095 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4098 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4101 g_object_unref (msg);
4103 headers_list = get_selected_headers (win);
4107 iter = tny_list_create_iterator (headers_list);
4109 header = TNY_HEADER (tny_iterator_get_current (iter));
4111 headers_action_show_details (header, win, NULL);
4112 g_object_unref (header);
4115 g_object_unref (iter);
4116 g_object_unref (headers_list);
4118 } else if (MODEST_IS_MAIN_WINDOW (win)) {
4119 GtkWidget *folder_view, *header_view;
4121 /* Check which widget has the focus */
4122 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4123 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4124 if (gtk_widget_is_focus (folder_view)) {
4125 TnyFolderStore *folder_store
4126 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4127 if (!folder_store) {
4128 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4131 /* Show only when it's a folder */
4132 /* This function should not be called for account items,
4133 * because we dim the menu item for them. */
4134 if (TNY_IS_FOLDER (folder_store)) {
4135 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4138 g_object_unref (folder_store);
4141 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4142 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4143 /* Show details of each header */
4144 do_headers_action (win, headers_action_show_details, header_view);
4150 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4151 ModestMsgEditWindow *window)
4153 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4155 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4159 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4160 ModestMsgEditWindow *window)
4162 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4164 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4168 modest_ui_actions_toggle_folders_view (GtkAction *action,
4169 ModestMainWindow *main_window)
4171 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4173 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4174 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4176 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4180 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4181 ModestWindow *window)
4183 gboolean active, fullscreen = FALSE;
4184 ModestWindowMgr *mgr;
4186 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4188 /* Check if we want to toggle the toolbar vuew in fullscreen
4190 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4191 "ViewShowToolbarFullScreen")) {
4195 /* Toggle toolbar */
4196 mgr = modest_runtime_get_window_mgr ();
4197 modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4201 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4202 ModestMsgEditWindow *window)
4204 modest_msg_edit_window_select_font (window);
4209 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4210 const gchar *display_name,
4213 /* don't update the display name if it was already set;
4214 * updating the display name apparently is expensive */
4215 const gchar* old_name = gtk_window_get_title (window);
4217 if (display_name == NULL)
4220 if (old_name && display_name && strcmp (old_name, display_name) == 0)
4221 return; /* don't do anything */
4223 /* This is usually used to change the title of the main window, which
4224 * is the one that holds the folder view. Note that this change can
4225 * happen even when the widget doesn't have the focus. */
4226 gtk_window_set_title (window, display_name);
4231 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4233 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4234 modest_msg_edit_window_select_contacts (window);
4238 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4240 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4241 modest_msg_edit_window_check_names (window, FALSE);
4245 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4247 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4248 GTK_WIDGET (user_data));
4252 * This function is used to track changes in the selection of the
4253 * folder view that is inside the "move to" dialog to enable/disable
4254 * the OK button because we do not want the user to select a disallowed
4255 * destination for a folder.
4256 * The user also not desired to be able to use NEW button on items where
4257 * folder creation is not possibel.
4260 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4261 TnyFolderStore *folder_store,
4265 GtkWidget *dialog = NULL;
4266 GtkWidget *ok_button = NULL, *new_button = NULL;
4267 GList *children = NULL;
4268 gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4269 gboolean moving_folder = FALSE;
4270 gboolean is_local_account = TRUE;
4271 GtkWidget *folder_view = NULL;
4272 ModestTnyFolderRules rules;
4274 g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4279 /* Get the OK button */
4280 dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4284 children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4285 ok_button = GTK_WIDGET (children->next->next->data);
4286 new_button = GTK_WIDGET (children->next->data);
4287 g_list_free (children);
4289 /* check if folder_store is an remote account */
4290 if (TNY_IS_ACCOUNT (folder_store)) {
4291 TnyAccount *local_account = NULL;
4292 TnyAccount *mmc_account = NULL;
4293 ModestTnyAccountStore *account_store = NULL;
4295 account_store = modest_runtime_get_account_store ();
4296 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4297 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4299 if ((gpointer) local_account != (gpointer) folder_store &&
4300 (gpointer) mmc_account != (gpointer) folder_store) {
4301 const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4302 ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4303 if (proto_name != NULL) {
4304 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4306 is_local_account = FALSE;
4307 /* New button should be dimmed on remote
4309 new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4311 g_object_unref (local_account);
4312 g_object_unref (mmc_account);
4315 /* Check the target folder rules */
4316 if (TNY_IS_FOLDER (folder_store)) {
4317 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4318 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4319 ok_sensitive = FALSE;
4320 new_sensitive = FALSE;
4325 /* Check if we're moving a folder */
4326 if (MODEST_IS_MAIN_WINDOW (user_data)) {
4327 /* Get the widgets */
4328 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4329 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4330 if (gtk_widget_is_focus (folder_view))
4331 moving_folder = TRUE;
4334 if (moving_folder) {
4335 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4337 /* Get the folder to move */
4338 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4340 /* Check that we're not moving to the same folder */
4341 if (TNY_IS_FOLDER (moved_folder)) {
4342 parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4343 if (parent == folder_store)
4344 ok_sensitive = FALSE;
4345 g_object_unref (parent);
4348 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4349 /* Do not allow to move to an account unless it's the
4350 local folders account */
4351 if (!is_local_account)
4352 ok_sensitive = FALSE;
4355 if (ok_sensitive && (moved_folder == folder_store)) {
4356 /* Do not allow to move to itself */
4357 ok_sensitive = FALSE;
4359 g_object_unref (moved_folder);
4361 TnyFolder *src_folder = NULL;
4363 /* Moving a message */
4364 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4366 TnyHeader *header = NULL;
4367 header = modest_msg_view_window_get_header
4368 (MODEST_MSG_VIEW_WINDOW (user_data));
4369 if (!TNY_IS_HEADER(header))
4370 g_warning ("%s: could not get source header", __FUNCTION__);
4372 src_folder = tny_header_get_folder (header);
4375 g_object_unref (header);
4378 TNY_FOLDER (modest_folder_view_get_selected
4379 (MODEST_FOLDER_VIEW (folder_view)));
4382 if (TNY_IS_FOLDER(src_folder)) {
4383 /* Do not allow to move the msg to the same folder */
4384 /* Do not allow to move the msg to an account */
4385 if ((gpointer) src_folder == (gpointer) folder_store ||
4386 TNY_IS_ACCOUNT (folder_store))
4387 ok_sensitive = FALSE;
4388 g_object_unref (src_folder);
4390 g_warning ("%s: could not get source folder", __FUNCTION__);
4394 /* Set sensitivity of the OK button */
4395 gtk_widget_set_sensitive (ok_button, ok_sensitive);
4396 /* Set sensitivity of the NEW button */
4397 gtk_widget_set_sensitive (new_button, new_sensitive);
4401 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4404 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4406 return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4407 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4411 create_move_to_dialog (GtkWindow *win,
4412 GtkWidget *folder_view,
4413 GtkWidget **tree_view)
4415 GtkWidget *dialog, *scroll;
4416 GtkWidget *new_button;
4418 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4420 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4423 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4424 /* We do this manually so GTK+ does not associate a response ID for
4426 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4427 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4428 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4430 /* Create scrolled window */
4431 scroll = gtk_scrolled_window_new (NULL, NULL);
4432 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
4433 GTK_POLICY_AUTOMATIC,
4434 GTK_POLICY_AUTOMATIC);
4436 /* Create folder view */
4437 *tree_view = modest_platform_create_folder_view (NULL);
4439 /* Track changes in the selection to
4440 * disable the OK button whenever "Move to" is not possible
4441 * disbale NEW button whenever New is not possible */
4442 g_signal_connect (*tree_view,
4443 "folder_selection_changed",
4444 G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4447 /* Listen to clicks on New button */
4448 g_signal_connect (G_OBJECT (new_button),
4450 G_CALLBACK(create_move_to_dialog_on_new_folder),
4453 /* It could happen that we're trying to move a message from a
4454 window (msg window for example) after the main window was
4455 closed, so we can not just get the model of the folder
4457 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4458 const gchar *visible_id = NULL;
4460 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4461 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4462 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4463 MODEST_FOLDER_VIEW(*tree_view));
4466 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4468 /* Show the same account than the one that is shown in the main window */
4469 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
4472 const gchar *active_account_name = NULL;
4473 ModestAccountMgr *mgr = NULL;
4474 ModestAccountSettings *settings = NULL;
4475 ModestServerAccountSettings *store_settings = NULL;
4477 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4478 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4479 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
4480 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4482 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4483 mgr = modest_runtime_get_account_mgr ();
4484 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4487 const gchar *store_account_name;
4488 store_settings = modest_account_settings_get_store_settings (settings);
4489 store_account_name = modest_server_account_settings_get_account_name (store_settings);
4491 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4492 store_account_name);
4493 g_object_unref (store_settings);
4494 g_object_unref (settings);
4498 /* we keep a pointer to the embedded folder view, so we can retrieve it with
4499 * get_folder_view_from_move_to_dialog
4500 * (see above) later (needed for focus handling)
4502 g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4505 /* Hide special folders */
4506 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4508 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4510 /* Add scroll to dialog */
4511 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
4512 scroll, TRUE, TRUE, 0);
4514 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4515 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4523 * Shows a confirmation dialog to the user when we're moving messages
4524 * from a remote server to the local storage. Returns the dialog
4525 * response. If it's other kind of movement then it always returns
4528 * This one is used by the next functions:
4529 * modest_ui_actions_on_paste - commented out
4530 * drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4533 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4534 TnyFolder *dest_folder,
4538 gint response = GTK_RESPONSE_OK;
4539 TnyAccount *account = NULL;
4540 TnyFolder *src_folder = NULL;
4541 TnyIterator *iter = NULL;
4542 TnyHeader *header = NULL;
4544 /* return with OK if the destination is a remote folder */
4545 if (modest_tny_folder_is_remote_folder (dest_folder))
4546 return GTK_RESPONSE_OK;
4548 /* Get source folder */
4549 iter = tny_list_create_iterator (headers);
4550 header = TNY_HEADER (tny_iterator_get_current (iter));
4552 src_folder = tny_header_get_folder (header);
4553 g_object_unref (header);
4555 g_object_unref (iter);
4557 /* if no src_folder, message may be an attahcment */
4558 if (src_folder == NULL)
4559 return GTK_RESPONSE_CANCEL;
4561 /* If the source is a local or MMC folder */
4562 if (!modest_tny_folder_is_remote_folder (src_folder)) {
4563 g_object_unref (src_folder);
4564 return GTK_RESPONSE_OK;
4567 /* Get the account */
4568 account = tny_folder_get_account (src_folder);
4570 /* now if offline we ask the user */
4571 if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4572 response = GTK_RESPONSE_OK;
4574 response = GTK_RESPONSE_CANCEL;
4577 g_object_unref (src_folder);
4578 g_object_unref (account);
4584 move_to_cb (ModestMailOperation *mail_op,
4587 MoveToHelper *helper = (MoveToHelper *) user_data;
4589 /* Note that the operation could have failed, in that case do
4591 if (modest_mail_operation_get_status (mail_op) ==
4592 MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4594 GObject *object = modest_mail_operation_get_source (mail_op);
4595 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4596 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4598 if (!modest_msg_view_window_select_next_message (self) &&
4599 !modest_msg_view_window_select_previous_message (self)) {
4600 /* No more messages to view, so close this window */
4601 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4603 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4604 GtkWidget *header_view;
4606 GtkTreeSelection *sel;
4608 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4609 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4610 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4611 path = gtk_tree_row_reference_get_path (helper->reference);
4612 /* We need to unselect the previous one
4613 because we could be copying instead of
4615 gtk_tree_selection_unselect_all (sel);
4616 gtk_tree_selection_select_path (sel, path);
4617 gtk_tree_path_free (path);
4619 g_object_unref (object);
4622 /* Close the "Pasting" information banner */
4623 gtk_widget_destroy (GTK_WIDGET(helper->banner));
4624 g_object_unref (helper->banner);
4625 if (helper->reference != NULL)
4626 gtk_tree_row_reference_free (helper->reference);
4631 folder_move_to_cb (ModestMailOperation *mail_op,
4632 TnyFolder *new_folder,
4635 GtkWidget *folder_view;
4638 object = modest_mail_operation_get_source (mail_op);
4639 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4640 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4641 g_object_ref (folder_view);
4642 g_object_unref (object);
4643 move_to_cb (mail_op, user_data);
4644 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4645 g_object_unref (folder_view);
4649 msgs_move_to_cb (ModestMailOperation *mail_op,
4652 move_to_cb (mail_op, user_data);
4656 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4659 ModestWindow *main_window = NULL;
4661 /* Disable next automatic folder selection */
4662 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4663 FALSE); /* don't create */
4665 GObject *win = NULL;
4666 GtkWidget *folder_view = NULL;
4668 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4669 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4670 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4672 if (user_data && TNY_IS_FOLDER (user_data)) {
4673 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
4674 TNY_FOLDER (user_data), FALSE);
4677 /* Show notification dialog only if the main window exists */
4678 win = modest_mail_operation_get_source (mail_op);
4679 modest_platform_run_information_dialog ((GtkWindow *) win,
4680 _("mail_in_ui_folder_move_target_error"),
4683 g_object_unref (win);
4688 open_msg_for_purge_cb (ModestMailOperation *mail_op,
4697 gint pending_purges = 0;
4698 gboolean some_purged = FALSE;
4699 ModestWindow *win = MODEST_WINDOW (user_data);
4700 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4702 /* If there was any error */
4703 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4704 modest_window_mgr_unregister_header (mgr, header);
4708 /* Once the message has been retrieved for purging, we check if
4709 * it's all ok for purging */
4711 parts = tny_simple_list_new ();
4712 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4713 iter = tny_list_create_iterator (parts);
4715 while (!tny_iterator_is_done (iter)) {
4717 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4718 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4719 if (tny_mime_part_is_purged (part))
4726 g_object_unref (part);
4728 tny_iterator_next (iter);
4730 g_object_unref (iter);
4733 if (pending_purges>0) {
4735 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4737 if (response == GTK_RESPONSE_OK) {
4738 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4739 iter = tny_list_create_iterator (parts);
4740 while (!tny_iterator_is_done (iter)) {
4743 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4744 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4745 tny_mime_part_set_purged (part);
4748 g_object_unref (part);
4750 tny_iterator_next (iter);
4752 g_object_unref (iter);
4754 tny_msg_rewrite_cache (msg);
4757 /* This string no longer exists, refer to NB#75415 for more info */
4758 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4761 modest_window_mgr_unregister_header (mgr, header);
4763 g_object_unref (parts);
4767 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4768 ModestMainWindow *win)
4770 GtkWidget *header_view;
4771 TnyList *header_list;
4773 TnyHeaderFlags flags;
4774 ModestWindow *msg_view_window = NULL;
4777 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4779 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4780 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4782 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4784 g_warning ("%s: no header selected", __FUNCTION__);
4788 if (tny_list_get_length (header_list) == 1) {
4789 TnyIterator *iter = tny_list_create_iterator (header_list);
4790 header = TNY_HEADER (tny_iterator_get_current (iter));
4791 g_object_unref (iter);
4795 if (!header || !TNY_IS_HEADER(header)) {
4796 g_warning ("%s: header is not valid", __FUNCTION__);
4800 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4801 header, &msg_view_window);
4802 flags = tny_header_get_flags (header);
4803 if (!(flags & TNY_HEADER_FLAG_CACHED))
4806 if (msg_view_window != NULL)
4807 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4809 /* do nothing; uid was registered before, so window is probably on it's way */
4810 g_warning ("debug: header %p has already been registered", header);
4813 ModestMailOperation *mail_op = NULL;
4814 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4815 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4816 modest_ui_actions_disk_operations_error_handler,
4818 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4819 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4821 g_object_unref (mail_op);
4824 g_object_unref (header);
4826 g_object_unref (header_list);
4830 * Checks if we need a connection to do the transfer and if the user
4831 * wants to connect to complete it
4834 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4835 TnyFolderStore *src_folder,
4837 TnyFolder *dst_folder,
4838 gboolean delete_originals,
4839 gboolean *need_connection,
4842 TnyAccount *src_account;
4843 gint uncached_msgs = 0;
4845 uncached_msgs = header_list_count_uncached_msgs (headers);
4847 /* We don't need any further check if
4849 * 1- the source folder is local OR
4850 * 2- the device is already online
4852 if (!modest_tny_folder_store_is_remote (src_folder) ||
4853 tny_device_is_online (modest_runtime_get_device())) {
4854 *need_connection = FALSE;
4859 /* We must ask for a connection when
4861 * - the message(s) is not already cached OR
4862 * - the message(s) is cached but the leave_on_server setting
4863 * is FALSE (because we need to sync the source folder to
4864 * delete the message from the server (for IMAP we could do it
4865 * offline, it'll take place the next time we get a
4868 src_account = get_account_from_folder_store (src_folder);
4869 if (uncached_msgs > 0) {
4873 *need_connection = TRUE;
4874 num_headers = tny_list_get_length (headers);
4875 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4877 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4878 GTK_RESPONSE_CANCEL) {
4884 /* The transfer is possible and the user wants to */
4887 if (remote_folder_is_pop (src_folder) && delete_originals) {
4888 const gchar *account_name;
4889 gboolean leave_on_server;
4891 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4892 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4895 if (leave_on_server == TRUE) {
4896 *need_connection = FALSE;
4898 *need_connection = TRUE;
4901 *need_connection = FALSE;
4906 g_object_unref (src_account);
4910 xfer_messages_error_handler (ModestMailOperation *mail_op,
4913 ModestWindow *main_window = NULL;
4915 /* Disable next automatic folder selection */
4916 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4917 FALSE); /* don't create */
4919 GObject *win = modest_mail_operation_get_source (mail_op);
4920 modest_platform_run_information_dialog ((GtkWindow *) win,
4921 _("mail_in_ui_folder_move_target_error"),
4924 g_object_unref (win);
4929 * Utility function that transfer messages from both the main window
4930 * and the msg view window when using the "Move to" dialog
4933 xfer_messages_performer (gboolean canceled,
4935 GtkWindow *parent_window,
4936 TnyAccount *account,
4939 TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4940 ModestWindow *win = MODEST_WINDOW (parent_window);
4941 TnyList *headers = NULL;
4942 TnyAccount *dst_account = NULL;
4943 const gchar *proto_str = NULL;
4944 gboolean dst_is_pop = FALSE;
4950 if (is_memory_full_error (err)) {
4951 modest_platform_information_banner ((GtkWidget *) parent_window,
4952 NULL, dgettext("ke-recv",
4953 "cerm_device_memory_full"));
4955 /* Show the proper error message */
4956 modest_ui_actions_on_account_connection_error (parent_window, account);
4961 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4962 proto_str = tny_account_get_proto (dst_account);
4964 /* tinymail will return NULL for local folders it seems */
4965 dst_is_pop = proto_str &&
4966 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
4967 MODEST_PROTOCOL_STORE_POP);
4969 g_object_unref (dst_account);
4971 /* Get selected headers */
4972 headers = get_selected_headers (MODEST_WINDOW (win));
4974 g_warning ("%s: no headers selected", __FUNCTION__);
4979 modest_platform_information_banner (GTK_WIDGET (win),
4981 ngettext("mail_in_ui_folder_move_target_error",
4982 "mail_in_ui_folder_move_targets_error",
4983 tny_list_get_length (headers)));
4984 g_object_unref (headers);
4988 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4989 helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4990 _CS("ckct_nw_pasting"));
4991 if (helper->banner != NULL) {
4992 g_object_ref (helper->banner);
4993 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4994 gtk_widget_show (GTK_WIDGET(helper->banner));
4997 if (MODEST_IS_MAIN_WINDOW (win)) {
4998 GtkWidget *header_view =
4999 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5000 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5001 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5004 ModestMailOperation *mail_op =
5005 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5006 xfer_messages_error_handler,
5008 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5011 modest_mail_operation_xfer_msgs (mail_op,
5013 TNY_FOLDER (dst_folder),
5018 g_object_unref (G_OBJECT (mail_op));
5019 g_object_unref (headers);
5021 g_object_unref (dst_folder);
5025 TnyFolder *src_folder;
5026 TnyFolderStore *dst_folder;
5027 gboolean delete_original;
5028 GtkWidget *folder_view;
5032 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5033 TnyAccount *account, gpointer user_data)
5035 MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5036 GtkTreeSelection *sel;
5037 ModestMailOperation *mail_op = NULL;
5039 if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5040 g_object_unref (G_OBJECT (info->src_folder));
5041 g_object_unref (G_OBJECT (info->dst_folder));
5046 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5047 helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5048 _CS("ckct_nw_pasting"));
5049 if (helper->banner != NULL) {
5050 g_object_ref (helper->banner);
5051 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
5052 gtk_widget_show (GTK_WIDGET(helper->banner));
5054 /* Clean folder on header view before moving it */
5055 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5056 gtk_tree_selection_unselect_all (sel);
5058 /* Let gtk events run. We need that the folder
5059 view frees its reference to the source
5060 folder *before* issuing the mail operation
5061 so we need the signal handler of selection
5062 changed to happen before the mail
5064 while (gtk_events_pending ())
5065 gtk_main_iteration (); */
5068 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5069 modest_ui_actions_move_folder_error_handler,
5070 info->src_folder, NULL);
5071 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5074 /* Select *after* the changes */
5075 /* TODO: this function hangs UI after transfer */
5076 /* modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5077 /* TNY_FOLDER (src_folder), TRUE); */
5079 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5080 TNY_FOLDER (info->dst_folder), TRUE);
5081 modest_mail_operation_xfer_folder (mail_op,
5082 TNY_FOLDER (info->src_folder),
5084 info->delete_original,
5087 g_object_unref (G_OBJECT (info->src_folder));
5089 /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) { */
5092 /* Unref mail operation */
5093 g_object_unref (G_OBJECT (mail_op));
5094 g_object_unref (G_OBJECT (info->dst_folder));
5099 get_account_from_folder_store (TnyFolderStore *folder_store)
5101 if (TNY_IS_ACCOUNT (folder_store))
5102 return g_object_ref (folder_store);
5104 return tny_folder_get_account (TNY_FOLDER (folder_store));
5108 * UI handler for the "Move to" action when invoked from the
5112 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5113 GtkWidget *folder_view,
5114 TnyFolderStore *dst_folder,
5115 ModestMainWindow *win)
5117 ModestHeaderView *header_view = NULL;
5118 TnyFolderStore *src_folder = NULL;
5120 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5122 /* Get the source folder */
5123 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5125 /* Get header view */
5126 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5128 /* Get folder or messages to transfer */
5129 if (gtk_widget_is_focus (folder_view)) {
5130 gboolean do_xfer = TRUE;
5132 /* Allow only to transfer folders to the local root folder */
5133 if (TNY_IS_ACCOUNT (dst_folder) &&
5134 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5135 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5137 } else if (!TNY_IS_FOLDER (src_folder)) {
5138 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5143 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5144 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5146 info->src_folder = g_object_ref (src_folder);
5147 info->dst_folder = g_object_ref (dst_folder);
5148 info->delete_original = TRUE;
5149 info->folder_view = folder_view;
5151 connect_info->callback = on_move_folder_cb;
5152 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5153 connect_info->data = info;
5155 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5156 TNY_FOLDER_STORE (src_folder),
5159 } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5162 headers = modest_header_view_get_selected_headers(header_view);
5164 /* Transfer the messages */
5165 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5166 headers, TNY_FOLDER (dst_folder));
5168 g_object_unref (headers);
5172 g_object_unref (src_folder);
5177 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5178 TnyFolder *src_folder,
5180 TnyFolder *dst_folder)
5182 gboolean need_connection = TRUE;
5183 gboolean do_xfer = TRUE;
5185 modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5186 headers, TNY_FOLDER (dst_folder),
5187 TRUE, &need_connection,
5190 /* If we don't want to transfer just return */
5194 if (need_connection) {
5195 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5196 connect_info->callback = xfer_messages_performer;
5197 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5198 connect_info->data = g_object_ref (dst_folder);
5200 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5201 TNY_FOLDER_STORE (src_folder),
5204 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5205 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5206 src_account, g_object_ref (dst_folder));
5207 g_object_unref (src_account);
5212 * UI handler for the "Move to" action when invoked from the
5213 * ModestMsgViewWindow
5216 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
5217 TnyFolderStore *dst_folder,
5218 ModestMsgViewWindow *win)
5220 TnyList *headers = NULL;
5221 TnyHeader *header = NULL;
5222 TnyFolder *src_folder = NULL;
5224 g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5226 /* Create header list */
5227 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5228 src_folder = TNY_FOLDER (tny_header_get_folder(header));
5229 headers = tny_simple_list_new ();
5230 tny_list_append (headers, G_OBJECT (header));
5232 /* Transfer the messages */
5233 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers,
5234 TNY_FOLDER (dst_folder));
5237 g_object_unref (header);
5238 g_object_unref (headers);
5242 modest_ui_actions_on_move_to (GtkAction *action,
5245 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5247 TnyFolderStore *dst_folder = NULL;
5248 ModestMainWindow *main_window;
5250 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5251 MODEST_IS_MSG_VIEW_WINDOW (win));
5253 /* Get the main window if exists */
5254 if (MODEST_IS_MAIN_WINDOW (win))
5255 main_window = MODEST_MAIN_WINDOW (win);
5258 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5259 FALSE)); /* don't create */
5261 /* Get the folder view widget if exists */
5263 folder_view = modest_main_window_get_child_widget (main_window,
5264 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5268 /* Create and run the dialog */
5269 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5270 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5271 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5272 result = gtk_dialog_run (GTK_DIALOG(dialog));
5273 g_object_ref (tree_view);
5274 gtk_widget_destroy (dialog);
5276 if (result != GTK_RESPONSE_ACCEPT)
5279 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5280 /* Do window specific stuff */
5281 if (MODEST_IS_MAIN_WINDOW (win)) {
5282 modest_ui_actions_on_main_window_move_to (action,
5285 MODEST_MAIN_WINDOW (win));
5287 modest_ui_actions_on_msg_view_window_move_to (action,
5289 MODEST_MSG_VIEW_WINDOW (win));
5293 g_object_unref (dst_folder);
5297 * Calls #HeadersFunc for each header already selected in the main
5298 * window or the message currently being shown in the msg view window
5301 do_headers_action (ModestWindow *win,
5305 TnyList *headers_list = NULL;
5306 TnyIterator *iter = NULL;
5307 TnyHeader *header = NULL;
5308 TnyFolder *folder = NULL;
5311 headers_list = get_selected_headers (win);
5315 /* Get the folder */
5316 iter = tny_list_create_iterator (headers_list);
5317 header = TNY_HEADER (tny_iterator_get_current (iter));
5319 folder = tny_header_get_folder (header);
5320 g_object_unref (header);
5323 /* Call the function for each header */
5324 while (!tny_iterator_is_done (iter)) {
5325 header = TNY_HEADER (tny_iterator_get_current (iter));
5326 func (header, win, user_data);
5327 g_object_unref (header);
5328 tny_iterator_next (iter);
5331 /* Trick: do a poke status in order to speed up the signaling
5333 tny_folder_poke_status (folder);
5336 g_object_unref (folder);
5337 g_object_unref (iter);
5338 g_object_unref (headers_list);
5342 modest_ui_actions_view_attachment (GtkAction *action,
5343 ModestWindow *window)
5345 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5346 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5348 /* not supported window for this action */
5349 g_return_if_reached ();
5354 modest_ui_actions_save_attachments (GtkAction *action,
5355 ModestWindow *window)
5357 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5359 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
5362 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5364 /* not supported window for this action */
5365 g_return_if_reached ();
5370 modest_ui_actions_remove_attachments (GtkAction *action,
5371 ModestWindow *window)
5373 if (MODEST_IS_MAIN_WINDOW (window)) {
5374 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5375 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5376 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5378 /* not supported window for this action */
5379 g_return_if_reached ();
5384 modest_ui_actions_on_settings (GtkAction *action,
5389 dialog = modest_platform_get_global_settings_dialog ();
5390 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5391 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5392 gtk_widget_show_all (dialog);
5394 gtk_dialog_run (GTK_DIALOG (dialog));
5396 gtk_widget_destroy (dialog);
5400 modest_ui_actions_on_help (GtkAction *action,
5403 const gchar *help_id;
5405 g_return_if_fail (action);
5406 g_return_if_fail (win && GTK_IS_WINDOW(win));
5408 help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5411 modest_platform_show_help (GTK_WINDOW (win), help_id);
5413 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5417 retrieve_msg_contents_performer (gboolean canceled,
5419 GtkWindow *parent_window,
5420 TnyAccount *account,
5423 ModestMailOperation *mail_op;
5424 TnyList *headers = TNY_LIST (user_data);
5426 if (err || canceled) {
5427 if (err && is_memory_full_error (err)) {
5428 modest_platform_information_banner ((GtkWidget *) parent_window,
5429 NULL, dgettext("ke-recv",
5430 "cerm_device_memory_full"));
5435 /* Create mail operation */
5436 mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5437 modest_ui_actions_disk_operations_error_handler,
5439 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5440 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5443 g_object_unref (mail_op);
5445 g_object_unref (headers);
5446 g_object_unref (account);
5450 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5451 ModestWindow *window)
5453 TnyList *headers = NULL;
5454 TnyAccount *account = NULL;
5455 TnyIterator *iter = NULL;
5456 TnyHeader *header = NULL;
5457 TnyFolder *folder = NULL;
5460 headers = get_selected_headers (window);
5464 /* Pick the account */
5465 iter = tny_list_create_iterator (headers);
5466 header = TNY_HEADER (tny_iterator_get_current (iter));
5467 folder = tny_header_get_folder (header);
5468 account = tny_folder_get_account (folder);
5469 g_object_unref (folder);
5470 g_object_unref (header);
5471 g_object_unref (iter);
5473 /* Connect and perform the message retrieval */
5474 modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5475 g_object_ref (account),
5476 retrieve_msg_contents_performer,
5477 g_object_ref (headers));
5480 g_object_unref (account);
5481 g_object_unref (headers);
5485 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5487 g_return_if_fail (MODEST_IS_WINDOW (window));
5490 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5494 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5496 g_return_if_fail (MODEST_IS_WINDOW (window));
5499 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5503 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5504 ModestWindow *window)
5506 g_return_if_fail (MODEST_IS_WINDOW (window));
5509 modest_ui_actions_check_menu_dimming_rules (window);
5513 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5514 ModestWindow *window)
5516 g_return_if_fail (MODEST_IS_WINDOW (window));
5519 modest_ui_actions_check_menu_dimming_rules (window);
5523 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5524 ModestWindow *window)
5526 g_return_if_fail (MODEST_IS_WINDOW (window));
5529 modest_ui_actions_check_menu_dimming_rules (window);
5533 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5534 ModestWindow *window)
5536 g_return_if_fail (MODEST_IS_WINDOW (window));
5539 modest_ui_actions_check_menu_dimming_rules (window);
5543 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5544 ModestWindow *window)
5546 g_return_if_fail (MODEST_IS_WINDOW (window));
5549 modest_ui_actions_check_menu_dimming_rules (window);
5553 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5554 ModestWindow *window)
5556 g_return_if_fail (MODEST_IS_WINDOW (window));
5559 modest_ui_actions_check_menu_dimming_rules (window);
5563 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5564 ModestWindow *window)
5566 g_return_if_fail (MODEST_IS_WINDOW (window));
5569 modest_ui_actions_check_menu_dimming_rules (window);
5573 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5574 ModestWindow *window)
5576 g_return_if_fail (MODEST_IS_WINDOW (window));
5579 modest_ui_actions_check_menu_dimming_rules (window);
5583 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5584 ModestWindow *window)
5586 g_return_if_fail (MODEST_IS_WINDOW (window));
5589 modest_ui_actions_check_menu_dimming_rules (window);
5593 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5595 g_return_if_fail (MODEST_IS_WINDOW (window));
5597 /* we check for low-mem; in that case, show a warning, and don't allow
5600 if (modest_platform_check_memory_low (window))
5603 modest_platform_show_search_messages (GTK_WINDOW (window));
5607 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5609 g_return_if_fail (MODEST_IS_WINDOW (win));
5612 /* we check for low-mem; in that case, show a warning, and don't allow
5613 * for the addressbook
5615 if (modest_platform_check_memory_low (win))
5619 modest_platform_show_addressbook (GTK_WINDOW (win));
5624 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5625 ModestWindow *window)
5627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5629 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5633 on_send_receive_finished (ModestMailOperation *mail_op,
5636 GtkWidget *header_view, *folder_view;
5637 TnyFolderStore *folder_store;
5638 ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5640 /* Set send/receive operation finished */
5641 modest_main_window_notify_send_receive_completed (main_win);
5643 /* Don't refresh the current folder if there were any errors */
5644 if (modest_mail_operation_get_status (mail_op) !=
5645 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5648 /* Refresh the current folder if we're viewing a window. We do
5649 this because the user won't be able to see the new mails in
5650 the selected folder after a Send&Receive because it only
5651 performs a poke_status, i.e, only the number of read/unread
5652 messages is updated, but the new headers are not
5654 folder_view = modest_main_window_get_child_widget (main_win,
5655 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5659 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5661 /* Do not need to refresh INBOX again because the
5662 update_account does it always automatically */
5663 if (folder_store && TNY_IS_FOLDER (folder_store) &&
5664 tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5665 ModestMailOperation *refresh_op;
5667 header_view = modest_main_window_get_child_widget (main_win,
5668 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5670 /* We do not need to set the contents style
5671 because it hasn't changed. We also do not
5672 need to save the widget status. Just force
5674 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5675 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5676 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5677 folder_refreshed_cb, main_win);
5678 g_object_unref (refresh_op);
5682 g_object_unref (folder_store);
5687 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5693 const gchar* server_name = NULL;
5694 TnyTransportAccount *server_account;
5695 gchar *message = NULL;
5697 /* Don't show anything if the user cancelled something or the send receive request is not
5699 if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5700 !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5704 /* Get the server name: */
5706 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5708 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5710 g_return_if_reached ();
5712 /* Show the appropriate message text for the GError: */
5713 switch (err->code) {
5714 case TNY_SERVICE_ERROR_CONNECT:
5715 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5717 case TNY_SERVICE_ERROR_AUTHENTICATE:
5718 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5720 case TNY_SERVICE_ERROR_SEND:
5721 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5723 case TNY_SERVICE_ERROR_UNAVAILABLE:
5724 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5727 g_warning ("%s: unexpected ERROR %d",
5728 __FUNCTION__, err->code);
5729 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5733 /* TODO if the username or the password where not defined we
5734 should show the Accounts Settings dialog or the Connection
5735 specific SMTP server window */
5737 modest_platform_run_information_dialog (NULL, message, FALSE);
5739 g_object_unref (server_account);
5743 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5748 ModestMainWindow *main_window = NULL;
5749 ModestWindowMgr *mgr = NULL;
5750 GtkWidget *folder_view = NULL, *header_view = NULL;
5751 TnyFolderStore *selected_folder = NULL;
5752 TnyFolderType folder_type;
5754 mgr = modest_runtime_get_window_mgr ();
5755 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5756 FALSE));/* don't create */
5760 /* Check if selected folder is OUTBOX */
5761 folder_view = modest_main_window_get_child_widget (main_window,
5762 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5763 header_view = modest_main_window_get_child_widget (main_window,
5764 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5766 selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5767 if (!TNY_IS_FOLDER (selected_folder))
5770 /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5771 #if GTK_CHECK_VERSION(2, 8, 0)
5772 folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder));
5773 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
5774 GtkTreeViewColumn *tree_column;
5776 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5777 TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5778 gtk_tree_view_column_queue_resize (tree_column);
5781 gtk_widget_queue_draw (header_view);
5784 /* Rerun dimming rules, because the message could become deletable for example */
5785 modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window),
5786 MODEST_DIMMING_RULES_TOOLBAR);
5790 if (selected_folder != NULL)
5791 g_object_unref (selected_folder);
5795 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5796 TnyAccount *account)
5798 ModestTransportStoreProtocol proto;
5799 const gchar *proto_name;
5800 gchar *error_note = NULL;
5802 proto_name = tny_account_get_proto (account);
5803 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5806 case MODEST_PROTOCOL_STORE_POP:
5807 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"),
5808 tny_account_get_hostname (account));
5810 case MODEST_PROTOCOL_STORE_IMAP:
5811 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"),
5812 tny_account_get_hostname (account));
5814 case MODEST_PROTOCOL_STORE_MAILDIR:
5815 case MODEST_PROTOCOL_STORE_MBOX:
5816 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5819 g_warning ("%s: This should not be reached", __FUNCTION__);
5823 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5824 g_free (error_note);
5829 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5832 TnyFolderStore *folder = NULL;
5833 TnyAccount *account = NULL;
5834 ModestTransportStoreProtocol proto;
5835 TnyHeader *header = NULL;
5837 if (MODEST_IS_MAIN_WINDOW (win)) {
5838 GtkWidget *header_view;
5839 TnyList* headers = NULL;
5841 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5842 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5843 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5844 if (!headers || tny_list_get_length (headers) == 0) {
5846 g_object_unref (headers);
5849 iter = tny_list_create_iterator (headers);
5850 header = TNY_HEADER (tny_iterator_get_current (iter));
5851 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5852 g_object_unref (iter);
5853 g_object_unref (headers);
5854 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5855 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5856 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5859 /* Get the account type */
5860 account = tny_folder_get_account (TNY_FOLDER (folder));
5861 proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5862 if (proto == MODEST_PROTOCOL_STORE_POP) {
5863 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5864 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5866 subject = tny_header_dup_subject (header);
5867 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
5871 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5875 g_object_unref (account);
5876 g_object_unref (folder);
5877 g_object_unref (header);