1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #endif /*HAVE_CONFIG_H*/
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard-dialog.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
83 #include <gtkhtml/gtkhtml.h>
85 typedef struct _GetMsgAsyncHelper {
87 ModestMailOperation *mail_op;
94 typedef enum _ReplyForwardAction {
100 typedef struct _ReplyForwardHelper {
101 guint reply_forward_type;
102 ReplyForwardAction action;
104 GtkWidget *parent_window;
105 } ReplyForwardHelper;
107 typedef struct _MoveToHelper {
108 GtkTreeRowReference *reference;
112 typedef struct _PasteAsAttachmentHelper {
113 ModestMsgEditWindow *window;
115 } PasteAsAttachmentHelper;
119 * The do_headers_action uses this kind of functions to perform some
120 * action to each member of a list of headers
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
124 static void do_headers_action (ModestWindow *win,
128 static void open_msg_cb (ModestMailOperation *mail_op,
135 static void reply_forward_cb (ModestMailOperation *mail_op,
142 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
144 static void folder_refreshed_cb (ModestMailOperation *mail_op,
148 static void on_send_receive_finished (ModestMailOperation *mail_op,
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
153 static gboolean connect_to_get_msg (ModestWindow *win,
154 gint num_of_uncached_msgs,
155 TnyAccount *account);
157 static gboolean remote_folder_is_pop (TnyFolderStore *folder);
159 static void do_create_folder (GtkWindow *window,
160 TnyFolderStore *parent_folder,
161 const gchar *suggested_name);
163 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
165 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
167 static void transfer_messages_helper (GtkWindow *win,
168 TnyFolder *src_folder,
170 TnyFolder *dst_folder);
173 * This function checks whether a TnyFolderStore is a pop account
176 remote_folder_is_pop (TnyFolderStore *folder)
178 const gchar *proto = NULL;
179 TnyAccount *account = NULL;
181 g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
183 account = get_account_from_folder_store (folder);
184 proto = tny_account_get_proto (account);
185 g_object_unref (account);
187 return (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
190 /* FIXME: this should be merged with the similar code in modest-account-view-window */
191 /* Show the account creation wizard dialog.
192 * returns: TRUE if an account was created. FALSE if the user cancelled.
195 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
197 gboolean result = FALSE;
198 GtkWindow *dialog, *wizard;
199 gint dialog_response;
201 /* Show the easy-setup wizard: */
202 dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
204 /* old wizard is active already;
206 gtk_window_present (GTK_WINDOW(dialog));
211 /* there is no such wizard yet */
212 wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
213 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
215 /* always present a main window in the background
216 * we do it here, so we cannot end up with two wizards (as this
217 * function might be called in modest_window_mgr_get_main_window as well */
219 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
220 TRUE); /* create if not existent */
222 /* make sure the mainwindow is visible */
223 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
224 gtk_widget_show_all (GTK_WIDGET(win));
225 gtk_window_present (GTK_WINDOW(win));
227 dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
228 gtk_widget_destroy (GTK_WIDGET (wizard));
229 if (gtk_events_pending ())
230 gtk_main_iteration ();
232 if (dialog_response == GTK_RESPONSE_CANCEL) {
235 /* Check whether an account was created: */
236 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
243 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
246 const gchar *authors[] = {
247 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
250 about = gtk_about_dialog_new ();
251 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
252 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
253 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
254 _("Copyright (c) 2006, Nokia Corporation\n"
255 "All rights reserved."));
256 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
257 _("a modest e-mail client\n\n"
258 "design and implementation: Dirk-Jan C. Binnema\n"
259 "contributions from the fine people at KC and Ig\n"
260 "uses the tinymail email framework written by Philip van Hoof"));
261 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
262 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
263 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
264 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
266 gtk_dialog_run (GTK_DIALOG (about));
267 gtk_widget_destroy(about);
271 * Gets the list of currently selected messages. If the win is the
272 * main window, then it returns a newly allocated list of the headers
273 * selected in the header view. If win is the msg view window, then
274 * the value returned is a list with just a single header.
276 * The caller of this funcion must free the list.
279 get_selected_headers (ModestWindow *win)
281 if (MODEST_IS_MAIN_WINDOW(win)) {
282 GtkWidget *header_view;
284 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
285 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
286 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
288 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
289 /* for MsgViewWindows, we simply return a list with one element */
291 TnyList *list = NULL;
293 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
294 if (header != NULL) {
295 list = tny_simple_list_new ();
296 tny_list_prepend (list, G_OBJECT(header));
297 g_object_unref (G_OBJECT(header));
306 static GtkTreeRowReference *
307 get_next_after_selected_headers (ModestHeaderView *header_view)
309 GtkTreeSelection *sel;
310 GList *selected_rows, *node;
312 GtkTreeRowReference *result;
315 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
316 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
317 selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
319 if (selected_rows == NULL)
322 node = g_list_last (selected_rows);
323 path = gtk_tree_path_copy ((GtkTreePath *) node->data);
324 gtk_tree_path_next (path);
326 result = gtk_tree_row_reference_new (model, path);
328 gtk_tree_path_free (path);
329 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
330 g_list_free (selected_rows);
336 headers_action_mark_as_read (TnyHeader *header,
340 TnyHeaderFlags flags;
342 g_return_if_fail (TNY_IS_HEADER(header));
344 flags = tny_header_get_flags (header);
345 if (flags & TNY_HEADER_FLAG_SEEN) return;
346 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
350 headers_action_mark_as_unread (TnyHeader *header,
354 TnyHeaderFlags flags;
356 g_return_if_fail (TNY_IS_HEADER(header));
358 flags = tny_header_get_flags (header);
359 if (flags & TNY_HEADER_FLAG_SEEN) {
360 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
364 /** After deleing a message that is currently visible in a window,
365 * show the next message from the list, or close the window if there are no more messages.
368 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
370 /* Close msg view window or select next */
371 if (!modest_msg_view_window_select_next_message (win) &&
372 !modest_msg_view_window_select_previous_message (win)) {
374 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
380 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
382 TnyList *header_list = NULL;
383 TnyIterator *iter = NULL;
384 TnyHeader *header = NULL;
385 gchar *message = NULL;
388 ModestWindowMgr *mgr;
389 GtkWidget *header_view = NULL;
391 g_return_if_fail (MODEST_IS_WINDOW(win));
393 /* Check first if the header view has the focus */
394 if (MODEST_IS_MAIN_WINDOW (win)) {
396 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
397 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
398 if (!gtk_widget_is_focus (header_view))
402 /* Get the headers, either from the header view (if win is the main window),
403 * or from the message view window: */
404 header_list = get_selected_headers (win);
405 if (!header_list) return;
407 /* Check if any of the headers are already opened, or in the process of being opened */
408 if (MODEST_IS_MAIN_WINDOW (win)) {
409 gint opened_headers = 0;
411 iter = tny_list_create_iterator (header_list);
412 mgr = modest_runtime_get_window_mgr ();
413 while (!tny_iterator_is_done (iter)) {
414 header = TNY_HEADER (tny_iterator_get_current (iter));
416 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
418 g_object_unref (header);
420 tny_iterator_next (iter);
422 g_object_unref (iter);
424 if (opened_headers > 0) {
427 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
430 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
433 g_object_unref (header_list);
439 if (tny_list_get_length(header_list) == 1) {
440 iter = tny_list_create_iterator (header_list);
441 header = TNY_HEADER (tny_iterator_get_current (iter));
444 subject = tny_header_dup_subject (header);
445 desc = g_strdup_printf ("%s", subject);
447 g_object_unref (header);
450 g_object_unref (iter);
452 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
453 tny_list_get_length(header_list)), desc);
455 /* Confirmation dialog */
456 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
460 if (response == GTK_RESPONSE_OK) {
461 ModestWindow *main_window = NULL;
462 ModestWindowMgr *mgr = NULL;
463 GtkTreeModel *model = NULL;
464 GtkTreeSelection *sel = NULL;
465 GList *sel_list = NULL, *tmp = NULL;
466 GtkTreeRowReference *next_row_reference = NULL;
467 GtkTreeRowReference *prev_row_reference = NULL;
468 GtkTreePath *next_path = NULL;
469 GtkTreePath *prev_path = NULL;
470 ModestMailOperation *mail_op = NULL;
472 /* Find last selected row */
473 if (MODEST_IS_MAIN_WINDOW (win)) {
474 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
475 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
476 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
477 for (tmp=sel_list; tmp; tmp=tmp->next) {
478 if (tmp->next == NULL) {
479 prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
480 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
482 gtk_tree_path_prev (prev_path);
483 gtk_tree_path_next (next_path);
485 prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
486 next_row_reference = gtk_tree_row_reference_new (model, next_path);
491 /* Disable window dimming management */
492 modest_window_disable_dimming (MODEST_WINDOW(win));
494 /* Remove each header. If it's a view window header_view == NULL */
495 mail_op = modest_mail_operation_new ((GObject *) win);
496 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
498 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
499 g_object_unref (mail_op);
501 /* Enable window dimming management */
503 gtk_tree_selection_unselect_all (sel);
505 modest_window_enable_dimming (MODEST_WINDOW(win));
507 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
508 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
510 /* Get main window */
511 mgr = modest_runtime_get_window_mgr ();
512 main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
514 /* Move cursor to next row */
517 /* Select next or previous row */
518 if (gtk_tree_row_reference_valid (next_row_reference)) {
519 /* next_path = gtk_tree_row_reference_get_path (row_reference); */
520 gtk_tree_selection_select_path (sel, next_path);
522 else if (gtk_tree_row_reference_valid (prev_row_reference)) {
523 gtk_tree_selection_select_path (sel, prev_path);
527 if (next_row_reference != NULL)
528 gtk_tree_row_reference_free (next_row_reference);
529 if (next_path != NULL)
530 gtk_tree_path_free (next_path);
531 if (prev_row_reference != NULL)
532 gtk_tree_row_reference_free (prev_row_reference);
533 if (prev_path != NULL)
534 gtk_tree_path_free (prev_path);
537 /* Update toolbar dimming state */
539 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
542 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
543 g_list_free (sel_list);
549 g_object_unref (header_list);
555 /* delete either message or folder, based on where we are */
557 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
559 g_return_if_fail (MODEST_IS_WINDOW(win));
561 /* Check first if the header view has the focus */
562 if (MODEST_IS_MAIN_WINDOW (win)) {
564 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
565 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
566 if (gtk_widget_is_focus (w)) {
567 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
571 modest_ui_actions_on_delete_message (action, win);
575 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
577 ModestWindowMgr *mgr = NULL;
579 #ifdef MODEST_PLATFORM_MAEMO
580 modest_osso_save_state();
581 #endif /* MODEST_PLATFORM_MAEMO */
583 g_debug ("closing down, clearing %d item(s) from operation queue",
584 modest_mail_operation_queue_num_elements
585 (modest_runtime_get_mail_operation_queue()));
587 /* cancel all outstanding operations */
588 modest_mail_operation_queue_cancel_all
589 (modest_runtime_get_mail_operation_queue());
591 g_debug ("queue has been cleared");
594 /* Check if there are opened editing windows */
595 mgr = modest_runtime_get_window_mgr ();
596 modest_window_mgr_close_all_windows (mgr);
598 /* note: when modest-tny-account-store is finalized,
599 it will automatically set all network connections
602 /* gtk_main_quit (); */
606 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
610 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
612 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
613 /* gtk_widget_destroy (GTK_WIDGET (win)); */
614 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
615 /* gboolean ret_value; */
616 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
617 /* } else if (MODEST_IS_WINDOW (win)) { */
618 /* gtk_widget_destroy (GTK_WIDGET (win)); */
620 /* g_return_if_reached (); */
625 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
627 GtkClipboard *clipboard = NULL;
628 gchar *selection = NULL;
630 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
631 selection = gtk_clipboard_wait_for_text (clipboard);
633 /* Question: why is the clipboard being used here?
634 * It doesn't really make a lot of sense. */
638 modest_address_book_add_address (selection);
644 modest_ui_actions_on_accounts (GtkAction *action,
647 /* This is currently only implemented for Maemo */
648 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
649 if (!modest_ui_actions_run_account_setup_wizard (win))
650 g_debug ("%s: wizard was already running", __FUNCTION__);
654 /* Show the list of accounts */
655 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
656 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
658 /* The accounts dialog must be modal */
659 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
660 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
664 #ifdef MODEST_PLATFORM_MAEMO
666 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
668 /* Save any changes. */
669 modest_connection_specific_smtp_window_save_server_accounts (
670 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
671 gtk_widget_destroy (GTK_WIDGET (window));
677 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
679 /* This is currently only implemented for Maemo,
680 * because it requires an API (libconic) to detect different connection
683 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
685 /* Create the window if necessary: */
686 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
687 modest_connection_specific_smtp_window_fill_with_connections (
688 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
689 modest_runtime_get_account_mgr());
691 /* Show the window: */
692 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
693 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
694 gtk_widget_show (specific_window);
696 /* Save changes when the window is hidden: */
697 g_signal_connect (specific_window, "hide",
698 G_CALLBACK (on_smtp_servers_window_hide), win);
699 #endif /* MODEST_PLATFORM_MAEMO */
703 modest_ui_actions_compose_msg(ModestWindow *win,
706 const gchar *bcc_str,
707 const gchar *subject_str,
708 const gchar *body_str,
710 gboolean set_as_modified)
712 gchar *account_name = NULL;
714 TnyAccount *account = NULL;
715 TnyFolder *folder = NULL;
716 gchar *from_str = NULL, *signature = NULL, *body = NULL;
717 gboolean use_signature = FALSE;
718 ModestWindow *msg_win = NULL;
719 ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
720 ModestTnyAccountStore *store = modest_runtime_get_account_store();
721 GnomeVFSFileSize total_size, allowed_size;
723 /* we check for low-mem; in that case, show a warning, and don't allow
724 * composing a message with attachments
726 if (attachments && modest_platform_check_memory_low (win))
729 account_name = modest_account_mgr_get_default_account(mgr);
731 g_printerr ("modest: no account found\n");
734 account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
736 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
739 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
741 g_printerr ("modest: failed to find Drafts folder\n");
744 from_str = modest_account_mgr_get_from_string (mgr, account_name);
746 g_printerr ("modest: failed get from string for '%s'\n", account_name);
750 signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
751 if (body_str != NULL) {
752 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
754 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
757 msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
759 g_printerr ("modest: failed to create new msg\n");
763 /* Create and register edit window */
764 /* This is destroyed by TODO. */
766 allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
767 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
768 while (attachments) {
770 modest_msg_edit_window_attach_file_one(
771 (ModestMsgEditWindow *)msg_win,
772 attachments->data, allowed_size);
774 if (total_size > allowed_size) {
775 g_warning ("%s: total size: %u",
776 __FUNCTION__, (unsigned int)total_size);
779 allowed_size -= total_size;
781 attachments = g_slist_next(attachments);
783 modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
784 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
786 gtk_widget_show_all (GTK_WIDGET (msg_win));
792 g_free (account_name);
794 g_object_unref (G_OBJECT(account));
796 g_object_unref (G_OBJECT(folder));
798 g_object_unref (G_OBJECT(msg_win));
800 g_object_unref (G_OBJECT(msg));
804 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
806 /* if there are no accounts yet, just show the wizard */
807 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
808 if (!modest_ui_actions_run_account_setup_wizard (win))
811 modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
816 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
820 ModestMailOperationStatus status;
822 /* If there is no message or the operation was not successful */
823 status = modest_mail_operation_get_status (mail_op);
824 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
826 /* Remove the header from the preregistered uids */
827 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
845 OpenMsgBannerInfo *banner_info;
846 GHashTable *row_refs_per_header;
850 open_msg_banner_idle (gpointer userdata)
852 OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
854 gdk_threads_enter ();
855 banner_info->idle_handler = 0;
856 banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
857 g_object_ref (banner_info->banner);
859 gdk_threads_leave ();
866 open_msg_cb (ModestMailOperation *mail_op,
873 ModestWindowMgr *mgr = NULL;
874 ModestWindow *parent_win = NULL;
875 ModestWindow *win = NULL;
876 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
877 gchar *account = NULL;
879 gboolean open_in_editor = FALSE;
880 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
882 /* Do nothing if there was any problem with the mail
883 operation. The error will be shown by the error_handler of
884 the mail operation */
885 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
888 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
889 folder = tny_header_get_folder (header);
891 /* Mark header as read */
892 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
894 /* Gets folder type (OUTBOX headers will be opened in edit window */
895 if (modest_tny_folder_is_local_folder (folder)) {
896 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
897 if (folder_type == TNY_FOLDER_TYPE_INVALID)
898 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
902 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
903 TnyTransportAccount *traccount = NULL;
904 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
905 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
907 ModestTnySendQueue *send_queue = NULL;
908 ModestTnySendQueueStatus status;
910 account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
911 TNY_ACCOUNT(traccount)));
912 send_queue = modest_runtime_get_send_queue(traccount);
913 msg_id = modest_tny_send_queue_get_msg_id (header);
914 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
915 /* Only open messages in outbox with the editor if they are in Failed state */
916 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
917 open_in_editor = TRUE;
920 g_object_unref(traccount);
922 g_warning("Cannot get transport account for message in outbox!!");
924 } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
925 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
930 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
932 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
934 if (open_in_editor) {
935 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
936 gchar *from_header = NULL;
938 from_header = tny_header_dup_from (header);
940 /* we cannot edit without a valid account... */
941 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
942 if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
943 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
945 g_free (from_header);
951 GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
953 for (node = accounts; node != NULL; node = g_slist_next (node)) {
954 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
956 if (from && (strcmp (from_header, from) == 0)) {
958 account = g_strdup (node->data);
964 g_free (from_header);
965 g_slist_foreach (accounts, (GFunc) g_free, NULL);
966 g_slist_free (accounts);
969 win = modest_msg_edit_window_new (msg, account, TRUE);
974 gchar *uid = modest_tny_folder_get_header_unique_id (header);
976 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
977 GtkTreeRowReference *row_reference;
979 row_reference = (GtkTreeRowReference *) g_hash_table_lookup (helper->row_refs_per_header, header);
981 win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
982 helper->model, row_reference);
984 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
989 /* Register and show new window */
991 mgr = modest_runtime_get_window_mgr ();
992 modest_window_mgr_register_window (mgr, win);
993 g_object_unref (win);
994 gtk_widget_show_all (GTK_WIDGET(win));
997 /* Update toolbar dimming state */
998 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
999 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1005 g_object_unref (parent_win);
1006 g_object_unref (folder);
1010 is_memory_full_error (GError *error)
1012 if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
1013 error->code == TNY_IO_ERROR_WRITE ||
1014 error->code == TNY_IO_ERROR_READ) {
1022 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1025 const GError *error;
1026 GObject *win = NULL;
1027 ModestMailOperationStatus status;
1029 win = modest_mail_operation_get_source (mail_op);
1030 error = modest_mail_operation_get_error (mail_op);
1031 status = modest_mail_operation_get_status (mail_op);
1033 /* If the mail op has been cancelled then it's not an error:
1034 don't show any message */
1035 if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1036 if (is_memory_full_error ((GError *) error)) {
1037 modest_platform_information_banner ((GtkWidget *) win,
1038 NULL, dgettext("ke-recv",
1039 "cerm_device_memory_full"));
1040 } else if (user_data) {
1041 modest_platform_information_banner ((GtkWidget *) win,
1047 g_object_unref (win);
1051 * Returns the account a list of headers belongs to. It returns a
1052 * *new* reference so don't forget to unref it
1055 get_account_from_header_list (TnyList *headers)
1057 TnyAccount *account = NULL;
1059 if (tny_list_get_length (headers) > 0) {
1060 TnyIterator *iter = tny_list_create_iterator (headers);
1061 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1062 TnyFolder *folder = tny_header_get_folder (header);
1065 g_object_unref (header);
1067 while (!tny_iterator_is_done (iter)) {
1068 header = TNY_HEADER (tny_iterator_get_current (iter));
1069 folder = tny_header_get_folder (header);
1072 g_object_unref (header);
1074 tny_iterator_next (iter);
1079 account = tny_folder_get_account (folder);
1080 g_object_unref (folder);
1084 g_object_unref (header);
1086 g_object_unref (iter);
1092 foreach_unregister_headers (gpointer data,
1095 ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1096 TnyHeader *header = TNY_HEADER (data);
1098 modest_window_mgr_unregister_header (mgr, header);
1102 open_msgs_helper_destroyer (gpointer user_data)
1104 OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1106 if (helper->banner_info) {
1107 g_free (helper->banner_info->message);
1108 if (helper->banner_info->idle_handler > 0) {
1109 g_source_remove (helper->banner_info->idle_handler);
1110 helper->banner_info->idle_handler = 0;
1112 if (helper->banner_info->banner != NULL) {
1113 gtk_widget_destroy (helper->banner_info->banner);
1114 g_object_unref (helper->banner_info->banner);
1115 helper->banner_info->banner = NULL;
1117 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1118 helper->banner_info = NULL;
1120 g_object_unref (helper->model);
1121 g_object_unref (helper->headers);
1122 g_hash_table_destroy (helper->row_refs_per_header);
1123 g_slice_free (OpenMsgHelper, helper);
1127 open_msgs_performer(gboolean canceled,
1129 GtkWindow *parent_window,
1130 TnyAccount *account,
1133 ModestMailOperation *mail_op = NULL;
1134 const gchar *proto_name;
1136 ModestTransportStoreProtocol proto;
1137 TnyList *not_opened_headers;
1138 TnyConnectionStatus status;
1139 gboolean show_open_draft = FALSE;
1140 OpenMsgHelper *helper = NULL;
1142 helper = (OpenMsgHelper *) user_data;
1143 not_opened_headers = helper->headers;
1145 status = tny_account_get_connection_status (account);
1146 if (err || canceled) {
1147 /* Unregister the already registered headers */
1148 tny_list_foreach (not_opened_headers, foreach_unregister_headers,
1149 modest_runtime_get_window_mgr ());
1150 /* Free the helper */
1151 open_msgs_helper_destroyer (helper);
1153 /* In memory full conditions we could get this error here */
1154 if (err && is_memory_full_error (err)) {
1155 modest_platform_information_banner ((GtkWidget *) parent_window,
1156 NULL, dgettext("ke-recv",
1157 "cerm_device_memory_full"));
1162 /* Get the error message depending on the protocol */
1163 proto_name = tny_account_get_proto (account);
1164 if (proto_name != NULL) {
1165 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1167 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1170 /* Create the error messages */
1171 if (tny_list_get_length (not_opened_headers) == 1) {
1172 if (proto == MODEST_PROTOCOL_STORE_POP) {
1173 error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1174 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1175 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1176 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1177 gchar *subject = tny_header_dup_subject (header);
1178 error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1181 g_object_unref (header);
1182 g_object_unref (iter);
1187 TnyFolderType folder_type;
1189 iter = tny_list_create_iterator (not_opened_headers);
1190 header = TNY_HEADER (tny_iterator_get_current (iter));
1191 folder = tny_header_get_folder (header);
1192 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1193 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1194 g_object_unref (folder);
1195 g_object_unref (header);
1196 g_object_unref (iter);
1197 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1200 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1203 /* Create the mail operation */
1205 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1206 modest_ui_actions_disk_operations_error_handler,
1208 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1211 if (show_open_draft) {
1212 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1213 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1214 helper->banner_info->banner = NULL;
1215 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1216 helper->banner_info);
1219 modest_mail_operation_get_msgs_full (mail_op,
1223 open_msgs_helper_destroyer);
1228 g_object_unref (mail_op);
1229 g_object_unref (account);
1233 * This function is used by both modest_ui_actions_on_open and
1234 * modest_ui_actions_on_header_activated. This way we always do the
1235 * same when trying to open messages.
1238 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1240 ModestWindowMgr *mgr = NULL;
1241 TnyIterator *iter = NULL, *iter_not_opened = NULL;
1242 TnyList *not_opened_headers = NULL;
1243 TnyHeaderFlags flags = 0;
1244 TnyAccount *account;
1245 gint uncached_msgs = 0;
1246 GtkWidget *header_view;
1247 GtkTreeModel *model;
1248 GHashTable *refs_for_headers;
1249 OpenMsgHelper *helper;
1250 GtkTreeSelection *sel;
1251 GList *sel_list = NULL, *sel_list_iter = NULL;
1253 g_return_if_fail (headers != NULL);
1255 /* Check that only one message is selected for opening */
1256 if (tny_list_get_length (headers) != 1) {
1257 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1258 NULL, _("mcen_ib_select_one_message"));
1262 mgr = modest_runtime_get_window_mgr ();
1263 iter = tny_list_create_iterator (headers);
1265 /* Get the account */
1266 account = get_account_from_header_list (headers);
1271 /* Get the selections, we need to get the references to the
1272 rows here because the treeview/model could dissapear (the
1273 user might want to select another folder)*/
1274 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1275 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1276 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1277 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
1278 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1279 refs_for_headers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
1280 (GDestroyNotify) gtk_tree_row_reference_free);
1282 /* Look if we already have a message view for each header. If
1283 true, then remove the header from the list of headers to
1285 sel_list_iter = sel_list;
1286 not_opened_headers = tny_simple_list_new ();
1287 while (!tny_iterator_is_done (iter) && sel_list_iter) {
1289 ModestWindow *window = NULL;
1290 TnyHeader *header = NULL;
1291 gboolean found = FALSE;
1293 header = TNY_HEADER (tny_iterator_get_current (iter));
1295 flags = tny_header_get_flags (header);
1298 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1300 /* Do not open again the message and present the
1301 window to the user */
1304 gtk_window_present (GTK_WINDOW (window));
1306 /* the header has been registered already, we don't do
1307 * anything but wait for the window to come up*/
1308 g_debug ("header %p already registered, waiting for window", header);
1311 GtkTreeRowReference *row_reference;
1313 tny_list_append (not_opened_headers, G_OBJECT (header));
1314 /* Create a new row reference and add it to the hash table */
1315 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list_iter->data);
1316 g_hash_table_insert (refs_for_headers, header, row_reference);
1320 g_object_unref (header);
1323 tny_iterator_next (iter);
1324 sel_list_iter = g_list_next (sel_list_iter);
1326 g_object_unref (iter);
1328 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1329 g_list_free (sel_list);
1331 /* Open each message */
1332 if (tny_list_get_length (not_opened_headers) == 0) {
1333 g_hash_table_destroy (refs_for_headers);
1337 /* If some messages would have to be downloaded, ask the user to
1338 * make a connection. It's generally easier to do this here (in the mainloop)
1339 * than later in a thread:
1341 if (tny_list_get_length (not_opened_headers) > 0) {
1342 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1344 if (uncached_msgs > 0) {
1345 /* Allways download if we are online. */
1346 if (!tny_device_is_online (modest_runtime_get_device ())) {
1349 /* If ask for user permission to download the messages */
1350 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1351 ngettext("mcen_nc_get_msg",
1355 /* End if the user does not want to continue */
1356 if (response == GTK_RESPONSE_CANCEL) {
1357 g_hash_table_destroy (refs_for_headers);
1364 /* Register the headers before actually creating the windows: */
1365 iter_not_opened = tny_list_create_iterator (not_opened_headers);
1366 while (!tny_iterator_is_done (iter_not_opened)) {
1367 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1369 modest_window_mgr_register_header (mgr, header, NULL);
1370 g_object_unref (header);
1372 tny_iterator_next (iter_not_opened);
1374 g_object_unref (iter_not_opened);
1375 iter_not_opened = NULL;
1377 /* Create the helper. We need to get a reference to the model
1378 here because it could change while the message is readed
1379 (the user could switch between folders) */
1380 helper = g_slice_new (OpenMsgHelper);
1381 helper->model = g_object_ref (model);
1382 helper->headers = g_object_ref (not_opened_headers);
1383 helper->row_refs_per_header = refs_for_headers;
1384 helper->banner_info = NULL;
1386 /* Connect to the account and perform */
1387 if (uncached_msgs > 0) {
1388 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1389 open_msgs_performer, helper);
1391 /* Call directly the performer, do not need to connect */
1392 open_msgs_performer (FALSE, NULL, (GtkWindow *) win,
1393 g_object_ref (account), helper);
1398 g_object_unref (account);
1399 if (not_opened_headers)
1400 g_object_unref (not_opened_headers);
1404 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1408 /* we check for low-mem; in that case, show a warning, and don't allow
1411 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1415 headers = get_selected_headers (win);
1420 open_msgs_from_headers (headers, win);
1422 g_object_unref(headers);
1427 free_reply_forward_helper (gpointer data)
1429 ReplyForwardHelper *helper;
1431 helper = (ReplyForwardHelper *) data;
1432 g_free (helper->account_name);
1433 g_slice_free (ReplyForwardHelper, helper);
1437 reply_forward_cb (ModestMailOperation *mail_op,
1445 ReplyForwardHelper *rf_helper;
1446 ModestWindow *msg_win = NULL;
1447 ModestEditType edit_type;
1449 TnyAccount *account = NULL;
1450 ModestWindowMgr *mgr = NULL;
1451 gchar *signature = NULL;
1452 gboolean use_signature;
1454 /* If there was any error. The mail operation could be NULL,
1455 this means that we already have the message downloaded and
1456 that we didn't do a mail operation to retrieve it */
1457 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1460 g_return_if_fail (user_data != NULL);
1461 rf_helper = (ReplyForwardHelper *) user_data;
1463 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1464 rf_helper->account_name);
1465 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(),
1466 rf_helper->account_name,
1469 /* Create reply mail */
1470 switch (rf_helper->action) {
1473 modest_tny_msg_create_reply_msg (msg, header, from,
1474 (use_signature) ? signature : NULL,
1475 rf_helper->reply_forward_type,
1476 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1478 case ACTION_REPLY_TO_ALL:
1480 modest_tny_msg_create_reply_msg (msg, header, from,
1481 (use_signature) ? signature : NULL,
1482 rf_helper->reply_forward_type,
1483 MODEST_TNY_MSG_REPLY_MODE_ALL);
1484 edit_type = MODEST_EDIT_TYPE_REPLY;
1486 case ACTION_FORWARD:
1488 modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1489 rf_helper->reply_forward_type);
1490 edit_type = MODEST_EDIT_TYPE_FORWARD;
1493 g_return_if_reached ();
1500 g_printerr ("modest: failed to create message\n");
1504 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1505 rf_helper->account_name,
1506 TNY_ACCOUNT_TYPE_STORE);
1508 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1512 /* Create and register the windows */
1513 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1514 mgr = modest_runtime_get_window_mgr ();
1515 modest_window_mgr_register_window (mgr, msg_win);
1517 if (rf_helper->parent_window != NULL) {
1518 gdouble parent_zoom;
1520 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1521 modest_window_set_zoom (msg_win, parent_zoom);
1524 /* Show edit window */
1525 gtk_widget_show_all (GTK_WIDGET (msg_win));
1529 g_object_unref (msg_win);
1531 g_object_unref (G_OBJECT (new_msg));
1533 g_object_unref (G_OBJECT (account));
1534 /* g_object_unref (msg); */
1535 free_reply_forward_helper (rf_helper);
1538 /* Checks a list of headers. If any of them are not currently
1539 * downloaded (CACHED) then returns TRUE else returns FALSE.
1542 header_list_count_uncached_msgs (TnyList *header_list)
1545 gint uncached_messages = 0;
1547 iter = tny_list_create_iterator (header_list);
1548 while (!tny_iterator_is_done (iter)) {
1551 header = TNY_HEADER (tny_iterator_get_current (iter));
1553 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1554 uncached_messages ++;
1555 g_object_unref (header);
1558 tny_iterator_next (iter);
1560 g_object_unref (iter);
1562 return uncached_messages;
1565 /* Returns FALSE if the user does not want to download the
1566 * messages. Returns TRUE if the user allowed the download.
1569 connect_to_get_msg (ModestWindow *win,
1570 gint num_of_uncached_msgs,
1571 TnyAccount *account)
1573 GtkResponseType response;
1575 /* Allways download if we are online. */
1576 if (tny_device_is_online (modest_runtime_get_device ()))
1579 /* If offline, then ask for user permission to download the messages */
1580 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1581 ngettext("mcen_nc_get_msg",
1583 num_of_uncached_msgs));
1585 if (response == GTK_RESPONSE_CANCEL)
1588 return modest_platform_connect_and_wait((GtkWindow *) win, account);
1592 * Common code for the reply and forward actions
1595 reply_forward (ReplyForwardAction action, ModestWindow *win)
1597 ModestMailOperation *mail_op = NULL;
1598 TnyList *header_list = NULL;
1599 ReplyForwardHelper *rf_helper = NULL;
1600 guint reply_forward_type;
1601 gboolean continue_download = TRUE;
1602 gboolean do_retrieve = TRUE;
1604 g_return_if_fail (MODEST_IS_WINDOW(win));
1607 /* we check for low-mem; in that case, show a warning, and don't allow
1608 * reply/forward (because it could potentially require a lot of memory */
1609 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
1613 /* we need an account when editing */
1614 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1615 if (!modest_ui_actions_run_account_setup_wizard (win))
1619 header_list = get_selected_headers (win);
1623 reply_forward_type =
1624 modest_conf_get_int (modest_runtime_get_conf (),
1625 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1628 /* check if we need to download msg before asking about it */
1629 do_retrieve = (action == ACTION_FORWARD) ||
1630 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1633 gint num_of_unc_msgs;
1635 /* check that the messages have been previously downloaded */
1636 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1637 /* If there are any uncached message ask the user
1638 * whether he/she wants to download them. */
1639 if (num_of_unc_msgs) {
1640 TnyAccount *account = get_account_from_header_list (header_list);
1642 continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1643 g_object_unref (account);
1648 if (!continue_download) {
1649 g_object_unref (header_list);
1653 /* We assume that we can only select messages of the
1654 same folder and that we reply all of them from the
1655 same account. In fact the interface currently only
1656 allows single selection */
1659 rf_helper = g_slice_new0 (ReplyForwardHelper);
1660 rf_helper->reply_forward_type = reply_forward_type;
1661 rf_helper->action = action;
1662 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1664 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1665 rf_helper->parent_window = GTK_WIDGET (win);
1666 if (!rf_helper->account_name)
1667 rf_helper->account_name =
1668 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1670 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1673 /* Get header and message. Do not free them here, the
1674 reply_forward_cb must do it */
1675 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1676 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1677 if (!msg || !header) {
1679 g_object_unref (msg);
1680 g_printerr ("modest: no message found\n");
1683 reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1686 g_object_unref (header);
1691 /* Only reply/forward to one message */
1692 iter = tny_list_create_iterator (header_list);
1693 header = TNY_HEADER (tny_iterator_get_current (iter));
1694 g_object_unref (iter);
1697 /* Retrieve messages */
1700 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1701 modest_ui_actions_disk_operations_error_handler,
1703 modest_mail_operation_queue_add (
1704 modest_runtime_get_mail_operation_queue (), mail_op);
1706 modest_mail_operation_get_msg (mail_op,
1711 g_object_unref(mail_op);
1713 /* we put a ref here to prevent double unref as the reply
1714 * forward callback unrefs the header at its end */
1715 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1719 g_object_unref (header);
1725 g_object_unref (header_list);
1729 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1731 g_return_if_fail (MODEST_IS_WINDOW(win));
1733 reply_forward (ACTION_REPLY, win);
1737 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1739 g_return_if_fail (MODEST_IS_WINDOW(win));
1741 reply_forward (ACTION_FORWARD, win);
1745 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1747 g_return_if_fail (MODEST_IS_WINDOW(win));
1749 reply_forward (ACTION_REPLY_TO_ALL, win);
1753 modest_ui_actions_on_next (GtkAction *action,
1754 ModestWindow *window)
1756 if (MODEST_IS_MAIN_WINDOW (window)) {
1757 GtkWidget *header_view;
1759 header_view = modest_main_window_get_child_widget (
1760 MODEST_MAIN_WINDOW(window),
1761 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1765 modest_header_view_select_next (
1766 MODEST_HEADER_VIEW(header_view));
1767 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1768 modest_msg_view_window_select_next_message (
1769 MODEST_MSG_VIEW_WINDOW (window));
1771 g_return_if_reached ();
1776 modest_ui_actions_on_prev (GtkAction *action,
1777 ModestWindow *window)
1779 g_return_if_fail (MODEST_IS_WINDOW(window));
1781 if (MODEST_IS_MAIN_WINDOW (window)) {
1782 GtkWidget *header_view;
1783 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1784 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1788 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1789 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1790 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1792 g_return_if_reached ();
1797 modest_ui_actions_on_sort (GtkAction *action,
1798 ModestWindow *window)
1800 g_return_if_fail (MODEST_IS_WINDOW(window));
1802 if (MODEST_IS_MAIN_WINDOW (window)) {
1803 GtkWidget *header_view;
1804 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1805 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1807 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1812 /* Show sorting dialog */
1813 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1818 new_messages_arrived (ModestMailOperation *self,
1819 TnyList *new_headers,
1823 gboolean show_visual_notifications;
1825 source = modest_mail_operation_get_source (self);
1826 show_visual_notifications = (source) ? FALSE : TRUE;
1828 g_object_unref (source);
1830 /* Notify new messages have been downloaded. If the
1831 send&receive was invoked by the user then do not show any
1832 visual notification, only play a sound and activate the LED
1833 (for the Maemo version) */
1834 if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1835 modest_platform_on_new_headers_received (new_headers,
1836 show_visual_notifications);
1841 retrieve_all_messages_cb (GObject *source,
1843 guint retrieve_limit)
1849 window = GTK_WINDOW (source);
1850 msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
1851 num_msgs, retrieve_limit);
1853 /* Ask the user if they want to retrieve all the messages */
1855 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1856 _("mcen_bd_get_all"),
1857 _("mcen_bd_newest_only"));
1858 /* Free and return */
1860 return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1864 TnyAccount *account;
1866 gchar *account_name;
1867 gboolean poke_status;
1868 gboolean interactive;
1869 ModestMailOperation *mail_op;
1873 do_send_receive_performer (gboolean canceled,
1875 GtkWindow *parent_window,
1876 TnyAccount *account,
1879 SendReceiveInfo *info;
1881 info = (SendReceiveInfo *) user_data;
1883 if (err || canceled) {
1884 /* In memory full conditions we could get this error here */
1885 if (err && is_memory_full_error (err)) {
1886 modest_platform_information_banner ((GtkWidget *) parent_window,
1887 NULL, dgettext("ke-recv",
1888 "cerm_device_memory_full"));
1890 if (info->mail_op) {
1891 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
1897 /* Set send/receive operation in progress */
1898 if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1899 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1902 if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1903 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
1904 G_CALLBACK (on_send_receive_finished),
1907 /* Send & receive. */
1908 modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
1909 (info->win) ? retrieve_all_messages_cb : NULL,
1910 new_messages_arrived, info->win);
1915 g_object_unref (G_OBJECT (info->mail_op));
1916 if (info->account_name)
1917 g_free (info->account_name);
1919 g_object_unref (info->win);
1921 g_object_unref (info->account);
1922 g_slice_free (SendReceiveInfo, info);
1926 * This function performs the send & receive required actions. The
1927 * window is used to create the mail operation. Typically it should
1928 * always be the main window, but we pass it as argument in order to
1932 modest_ui_actions_do_send_receive (const gchar *account_name,
1933 gboolean force_connection,
1934 gboolean poke_status,
1935 gboolean interactive,
1938 gchar *acc_name = NULL;
1939 SendReceiveInfo *info;
1940 ModestTnyAccountStore *acc_store;
1942 /* If no account name was provided then get the current account, and if
1943 there is no current account then pick the default one: */
1944 if (!account_name) {
1946 acc_name = g_strdup (modest_window_get_active_account (win));
1948 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1950 g_printerr ("modest: cannot get default account\n");
1954 acc_name = g_strdup (account_name);
1957 acc_store = modest_runtime_get_account_store ();
1959 /* Create the info for the connect and perform */
1960 info = g_slice_new (SendReceiveInfo);
1961 info->account_name = acc_name;
1962 info->win = (win) ? g_object_ref (win) : NULL;
1963 info->poke_status = poke_status;
1964 info->interactive = interactive;
1965 info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1966 TNY_ACCOUNT_TYPE_STORE);
1967 /* We need to create the operation here, because otherwise it
1968 could happen that the queue emits the queue-empty signal
1969 while we're trying to connect the account */
1970 info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1971 modest_ui_actions_disk_operations_error_handler,
1973 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
1975 /* Invoke the connect and perform */
1976 modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
1977 force_connection, info->account,
1978 do_send_receive_performer, info);
1983 modest_ui_actions_do_cancel_send (const gchar *account_name,
1986 TnyTransportAccount *transport_account;
1987 TnySendQueue *send_queue = NULL;
1988 GError *error = NULL;
1990 /* Get transport account */
1992 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1993 (modest_runtime_get_account_store(),
1995 TNY_ACCOUNT_TYPE_TRANSPORT));
1996 if (!transport_account) {
1997 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2002 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
2003 if (!TNY_IS_SEND_QUEUE(send_queue)) {
2004 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2005 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2006 "modest: could not find send queue for account\n");
2008 /* Cancel the current send */
2009 tny_account_cancel (TNY_ACCOUNT (transport_account));
2011 /* Suspend all pending messages */
2012 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2016 if (transport_account != NULL)
2017 g_object_unref (G_OBJECT (transport_account));
2021 modest_ui_actions_cancel_send_all (ModestWindow *win)
2023 GSList *account_names, *iter;
2025 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2028 iter = account_names;
2030 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2031 iter = g_slist_next (iter);
2034 modest_account_mgr_free_account_names (account_names);
2035 account_names = NULL;
2039 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
2042 /* Check if accounts exist */
2043 gboolean accounts_exist =
2044 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2046 /* If not, allow the user to create an account before trying to send/receive. */
2047 if (!accounts_exist)
2048 modest_ui_actions_on_accounts (NULL, win);
2050 /* Cancel all sending operaitons */
2051 modest_ui_actions_cancel_send_all (win);
2055 * Refreshes all accounts. This function will be used by automatic
2059 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2060 gboolean force_connection,
2061 gboolean poke_status,
2062 gboolean interactive)
2064 GSList *account_names, *iter;
2066 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2069 iter = account_names;
2071 modest_ui_actions_do_send_receive ((const char*) iter->data,
2073 poke_status, interactive, win);
2074 iter = g_slist_next (iter);
2077 modest_account_mgr_free_account_names (account_names);
2078 account_names = NULL;
2082 * Handler of the click on Send&Receive button in the main toolbar
2085 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2087 /* Check if accounts exist */
2088 gboolean accounts_exist;
2091 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2093 /* If not, allow the user to create an account before trying to send/receive. */
2094 if (!accounts_exist)
2095 modest_ui_actions_on_accounts (NULL, win);
2097 /* Refresh the current folder. The if is always TRUE it's just an extra check */
2098 if (MODEST_IS_MAIN_WINDOW (win)) {
2099 GtkWidget *folder_view;
2100 TnyFolderStore *folder_store;
2103 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2104 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2108 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2111 g_object_unref (folder_store);
2114 /* Refresh the active account. Force the connection if needed
2115 and poke the status of all folders */
2116 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2121 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2124 GtkWidget *header_view;
2126 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2128 header_view = modest_main_window_get_child_widget (main_window,
2129 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2133 conf = modest_runtime_get_conf ();
2135 /* what is saved/restored is depending on the style; thus; we save with
2136 * old style, then update the style, and restore for this new style
2138 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2140 if (modest_header_view_get_style
2141 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2142 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2143 MODEST_HEADER_VIEW_STYLE_TWOLINES);
2145 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2146 MODEST_HEADER_VIEW_STYLE_DETAILS);
2148 modest_widget_memory_restore (conf, G_OBJECT(header_view),
2149 MODEST_CONF_HEADER_VIEW_KEY);
2154 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2156 ModestMainWindow *main_window)
2158 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2159 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2161 /* in the case the folder is empty, show the empty folder message and focus
2163 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2164 if (modest_header_view_is_empty (header_view)) {
2165 TnyFolder *folder = modest_header_view_get_folder (header_view);
2166 GtkWidget *folder_view =
2167 modest_main_window_get_child_widget (main_window,
2168 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2170 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2171 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2175 /* If no header has been selected then exit */
2180 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2181 gtk_widget_grab_focus (GTK_WIDGET(header_view));
2183 /* Update toolbar dimming state */
2184 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2185 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2189 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2191 ModestMainWindow *main_window)
2195 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2200 if (modest_header_view_count_selected_headers (header_view) > 1) {
2201 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2205 /* we check for low-mem; in that case, show a warning, and don't allow
2206 * activating headers
2208 if (modest_platform_check_memory_low (MODEST_WINDOW(main_window)))
2212 /* headers = tny_simple_list_new (); */
2213 /* tny_list_prepend (headers, G_OBJECT (header)); */
2214 headers = modest_header_view_get_selected_headers (header_view);
2216 open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2218 g_object_unref (headers);
2222 set_active_account_from_tny_account (TnyAccount *account,
2223 ModestWindow *window)
2225 const gchar *server_acc_name = tny_account_get_id (account);
2227 /* We need the TnyAccount provided by the
2228 account store because that is the one that
2229 knows the name of the Modest account */
2230 TnyAccount *modest_server_account = modest_server_account =
2231 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2232 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2234 if (!modest_server_account) {
2235 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2239 /* Update active account, but only if it's not a pseudo-account */
2240 if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2241 (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2242 const gchar *modest_acc_name =
2243 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2244 if (modest_acc_name)
2245 modest_window_set_active_account (window, modest_acc_name);
2248 g_object_unref (modest_server_account);
2253 folder_refreshed_cb (ModestMailOperation *mail_op,
2257 ModestMainWindow *win = NULL;
2258 GtkWidget *header_view;
2260 g_return_if_fail (TNY_IS_FOLDER (folder));
2262 win = MODEST_MAIN_WINDOW (user_data);
2264 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2267 TnyFolder *current_folder;
2269 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2270 if (current_folder != NULL && folder != current_folder) {
2271 g_object_unref (current_folder);
2273 } else if (current_folder)
2274 g_object_unref (current_folder);
2277 /* Check if folder is empty and set headers view contents style */
2278 if (tny_folder_get_all_count (folder) == 0)
2279 modest_main_window_set_contents_style (win,
2280 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2285 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2286 TnyFolderStore *folder_store,
2288 ModestMainWindow *main_window)
2291 GtkWidget *header_view;
2293 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2295 header_view = modest_main_window_get_child_widget(main_window,
2296 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2300 conf = modest_runtime_get_conf ();
2302 if (TNY_IS_ACCOUNT (folder_store)) {
2304 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2306 /* Show account details */
2307 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2310 if (TNY_IS_FOLDER (folder_store) && selected) {
2312 /* Update the active account */
2313 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2315 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2316 g_object_unref (account);
2320 /* Set the header style by default, it could
2321 be changed later by the refresh callback to
2323 modest_main_window_set_contents_style (main_window,
2324 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2326 /* Set folder on header view. This function
2327 will call tny_folder_refresh_async so we
2328 pass a callback that will be called when
2329 finished. We use that callback to set the
2330 empty view if there are no messages */
2331 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2332 TNY_FOLDER (folder_store),
2333 folder_refreshed_cb,
2336 /* Restore configuration. We need to do this
2337 *after* the set_folder because the widget
2338 memory asks the header view about its
2340 modest_widget_memory_restore (modest_runtime_get_conf (),
2341 G_OBJECT(header_view),
2342 MODEST_CONF_HEADER_VIEW_KEY);
2344 /* No need to save the header view
2345 configuration for Maemo because it only
2346 saves the sorting stuff and that it's
2347 already being done by the sort
2348 dialog. Remove it when the GNOME version
2349 has the same behaviour */
2350 #ifdef MODEST_PLATFORM_GNOME
2351 if (modest_main_window_get_contents_style (main_window) ==
2352 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2353 modest_widget_memory_save (conf, G_OBJECT (header_view),
2354 MODEST_CONF_HEADER_VIEW_KEY);
2356 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2360 /* Update dimming state */
2361 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2362 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2366 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2373 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2375 online = tny_device_is_online (modest_runtime_get_device());
2378 /* already online -- the item is simply not there... */
2379 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2381 GTK_MESSAGE_WARNING,
2383 _("The %s you selected cannot be found"),
2385 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2386 gtk_dialog_run (GTK_DIALOG(dialog));
2388 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2391 _("mcen_bd_dialog_cancel"),
2392 GTK_RESPONSE_REJECT,
2393 _("mcen_bd_dialog_ok"),
2394 GTK_RESPONSE_ACCEPT,
2396 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2397 "Do you want to get online?"), item);
2398 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2399 gtk_label_new (txt), FALSE, FALSE, 0);
2400 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2403 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2404 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2405 /* TODO: Comment about why is this commented out: */
2406 /* modest_platform_connect_and_wait (); */
2409 gtk_widget_destroy (dialog);
2413 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2416 /* g_message ("%s %s", __FUNCTION__, link); */
2421 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2424 modest_platform_activate_uri (link);
2428 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2431 modest_platform_show_uri_popup (link);
2435 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2438 /* we check for low-mem; in that case, show a warning, and don't allow
2439 * viewing attachments
2441 if (modest_platform_check_memory_low (MODEST_WINDOW(win)))
2444 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2448 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2449 const gchar *address,
2452 /* g_message ("%s %s", __FUNCTION__, address); */
2456 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2457 TnyMsg *saved_draft,
2460 ModestMsgEditWindow *edit_window;
2461 ModestMainWindow *win;
2463 /* FIXME. Make the header view sensitive again. This is a
2464 * temporary hack. See modest_ui_actions_on_save_to_drafts()
2466 win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2467 modest_runtime_get_window_mgr(), FALSE));
2469 GtkWidget *hdrview = modest_main_window_get_child_widget(
2470 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2471 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2474 edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2476 /* Set draft is there was no error */
2477 if (!modest_mail_operation_get_error (mail_op))
2478 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2480 g_object_unref(edit_window);
2484 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2486 TnyTransportAccount *transport_account;
2487 ModestMailOperation *mail_operation;
2489 gchar *account_name, *from;
2490 ModestAccountMgr *account_mgr;
2491 /* char *info_text; */
2492 gboolean had_error = FALSE;
2493 guint64 available_disk, expected_size;
2496 ModestMainWindow *win;
2498 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2500 data = modest_msg_edit_window_get_msg_data (edit_window);
2503 available_disk = modest_folder_available_space (NULL);
2504 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2505 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2510 if ((available_disk != -1) && expected_size > available_disk) {
2511 modest_msg_edit_window_free_msg_data (edit_window, data);
2513 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2519 * djcb: if we're in low-memory state, we only allow for
2520 * saving messages smaller than
2521 * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2522 * should still allow for sending anything critical...
2524 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2526 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2527 modest_msg_edit_window_free_msg_data (edit_window, data);
2532 account_name = g_strdup (data->account_name);
2533 account_mgr = modest_runtime_get_account_mgr();
2535 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2537 account_name = modest_account_mgr_get_default_account (account_mgr);
2538 if (!account_name) {
2539 g_printerr ("modest: no account found\n");
2540 modest_msg_edit_window_free_msg_data (edit_window, data);
2544 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2545 account_name = g_strdup (data->account_name);
2549 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2550 (modest_runtime_get_account_store(),
2552 TNY_ACCOUNT_TYPE_TRANSPORT));
2553 if (!transport_account) {
2554 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2555 g_free (account_name);
2556 modest_msg_edit_window_free_msg_data (edit_window, data);
2559 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2561 /* Create the mail operation */
2562 mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2564 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2566 modest_mail_operation_save_to_drafts (mail_operation,
2578 data->priority_flags,
2579 on_save_to_drafts_cb,
2580 g_object_ref(edit_window));
2582 /* Use the main window as the parent of the banner, if the
2583 main window does not exist it won't be shown, if the parent
2584 window exists then it's properly shown. We don't use the
2585 editor window because it could be closed (save to drafts
2586 could happen after closing the window */
2587 win = (ModestMainWindow *)
2588 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2590 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2591 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2594 modest_msg_edit_window_set_modified (edit_window, FALSE);
2598 g_free (account_name);
2599 g_object_unref (G_OBJECT (transport_account));
2600 g_object_unref (G_OBJECT (mail_operation));
2602 modest_msg_edit_window_free_msg_data (edit_window, data);
2605 * If the drafts folder is selected then make the header view
2606 * insensitive while the message is being saved to drafts
2607 * (it'll be sensitive again in on_save_to_drafts_cb()). This
2608 * is not very clean but it avoids letting the drafts folder
2609 * in an inconsistent state: the user could edit the message
2610 * being saved and undesirable things would happen.
2611 * In the average case the user won't notice anything at
2612 * all. In the worst case (the user is editing a really big
2613 * file from Drafts) the header view will be insensitive
2614 * during the saving process (10 or 20 seconds, depending on
2615 * the message). Anyway this is just a quick workaround: once
2616 * we find a better solution it should be removed
2617 * See NB#65125 (commend #18) for details.
2619 if (!had_error && win != NULL) {
2620 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2621 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2623 TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2625 if (modest_tny_folder_is_local_folder(folder)) {
2626 TnyFolderType folder_type;
2627 folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2628 if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2629 GtkWidget *hdrview = modest_main_window_get_child_widget(
2630 win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2631 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2635 if (folder != NULL) g_object_unref(folder);
2642 /* For instance, when clicking the Send toolbar button when editing a message: */
2644 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2646 TnyTransportAccount *transport_account = NULL;
2647 gboolean had_error = FALSE;
2648 guint64 available_disk, expected_size;
2652 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2654 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2657 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2660 available_disk = modest_folder_available_space (NULL);
2661 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2662 expected_size = modest_tny_msg_estimate_size (data->plain_body,
2667 if ((available_disk != -1) && expected_size > available_disk) {
2668 modest_msg_edit_window_free_msg_data (edit_window, data);
2670 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2676 * djcb: if we're in low-memory state, we only allow for sending messages
2677 * smaller than MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h)
2678 * this should still allow for sending anything critical...
2680 if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2681 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window))) {
2682 modest_msg_edit_window_free_msg_data (edit_window, data);
2688 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2689 gchar *account_name = g_strdup (data->account_name);
2691 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2694 account_name = modest_account_mgr_get_default_account (account_mgr);
2696 if (!account_name) {
2697 modest_msg_edit_window_free_msg_data (edit_window, data);
2698 /* Run account setup wizard */
2699 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2704 /* Get the currently-active transport account for this modest account: */
2705 if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2706 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2707 (modest_runtime_get_account_store(),
2708 account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2711 if (!transport_account) {
2712 modest_msg_edit_window_free_msg_data (edit_window, data);
2713 /* Run account setup wizard */
2714 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2718 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2720 /* Create the mail operation */
2721 ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2722 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2724 modest_mail_operation_send_new_mail (mail_operation,
2736 data->priority_flags);
2738 if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2739 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2742 if (modest_mail_operation_get_error (mail_operation) != NULL) {
2743 const GError *error = modest_mail_operation_get_error (mail_operation);
2744 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2745 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2746 modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2753 g_free (account_name);
2754 g_object_unref (G_OBJECT (transport_account));
2755 g_object_unref (G_OBJECT (mail_operation));
2757 modest_msg_edit_window_free_msg_data (edit_window, data);
2760 modest_msg_edit_window_set_sent (edit_window, TRUE);
2762 /* Save settings and close the window: */
2763 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2770 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2771 ModestMsgEditWindow *window)
2773 ModestMsgEditFormatState *format_state = NULL;
2775 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2776 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2778 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2781 format_state = modest_msg_edit_window_get_format_state (window);
2782 g_return_if_fail (format_state != NULL);
2784 format_state->bold = gtk_toggle_action_get_active (action);
2785 modest_msg_edit_window_set_format_state (window, format_state);
2786 g_free (format_state);
2791 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2792 ModestMsgEditWindow *window)
2794 ModestMsgEditFormatState *format_state = NULL;
2796 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2797 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2799 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2802 format_state = modest_msg_edit_window_get_format_state (window);
2803 g_return_if_fail (format_state != NULL);
2805 format_state->italics = gtk_toggle_action_get_active (action);
2806 modest_msg_edit_window_set_format_state (window, format_state);
2807 g_free (format_state);
2812 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2813 ModestMsgEditWindow *window)
2815 ModestMsgEditFormatState *format_state = NULL;
2817 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2818 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2820 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2823 format_state = modest_msg_edit_window_get_format_state (window);
2824 g_return_if_fail (format_state != NULL);
2826 format_state->bullet = gtk_toggle_action_get_active (action);
2827 modest_msg_edit_window_set_format_state (window, format_state);
2828 g_free (format_state);
2833 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2834 GtkRadioAction *selected,
2835 ModestMsgEditWindow *window)
2837 ModestMsgEditFormatState *format_state = NULL;
2838 GtkJustification value;
2840 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2842 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2845 value = gtk_radio_action_get_current_value (selected);
2847 format_state = modest_msg_edit_window_get_format_state (window);
2848 g_return_if_fail (format_state != NULL);
2850 format_state->justification = value;
2851 modest_msg_edit_window_set_format_state (window, format_state);
2852 g_free (format_state);
2856 modest_ui_actions_on_select_editor_color (GtkAction *action,
2857 ModestMsgEditWindow *window)
2859 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2860 g_return_if_fail (GTK_IS_ACTION (action));
2862 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2865 modest_msg_edit_window_select_color (window);
2869 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2870 ModestMsgEditWindow *window)
2872 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2873 g_return_if_fail (GTK_IS_ACTION (action));
2875 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2878 modest_msg_edit_window_select_background_color (window);
2882 modest_ui_actions_on_insert_image (GtkAction *action,
2883 ModestMsgEditWindow *window)
2885 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2886 g_return_if_fail (GTK_IS_ACTION (action));
2889 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2892 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2895 modest_msg_edit_window_insert_image (window);
2899 modest_ui_actions_on_attach_file (GtkAction *action,
2900 ModestMsgEditWindow *window)
2902 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2903 g_return_if_fail (GTK_IS_ACTION (action));
2905 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
2908 modest_msg_edit_window_offer_attach_file (window);
2912 modest_ui_actions_on_remove_attachments (GtkAction *action,
2913 ModestMsgEditWindow *window)
2915 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2916 g_return_if_fail (GTK_IS_ACTION (action));
2918 modest_msg_edit_window_remove_attachments (window, NULL);
2922 do_create_folder_cb (ModestMailOperation *mail_op,
2923 TnyFolderStore *parent_folder,
2924 TnyFolder *new_folder,
2927 gchar *suggested_name = (gchar *) user_data;
2928 GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2930 if (modest_mail_operation_get_error (mail_op)) {
2932 /* Show an error. If there was some problem writing to
2933 disk, show it, otherwise show the generic folder
2934 create error. We do it here and not in an error
2935 handler because the call to do_create_folder will
2936 stop the main loop in a gtk_dialog_run and then,
2937 the message won't be shown until that dialog is
2939 modest_ui_actions_disk_operations_error_handler (mail_op,
2940 _("mail_in_ui_folder_create_error"));
2942 /* Try again. Do *NOT* show any error because the mail
2943 operations system will do it for us because we
2944 created the mail_op with new_with_error_handler */
2945 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2947 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2948 * FIXME: any other? */
2949 GtkWidget *folder_view;
2951 if (MODEST_IS_MAIN_WINDOW(source_win))
2953 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2954 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2957 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2959 /* Select the newly created folder. It could happen
2960 that the widget is no longer there (i.e. the window
2961 has been destroyed, so we need to check this */
2963 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2965 g_object_unref (new_folder);
2967 /* Free. Note that the first time it'll be NULL so noop */
2968 g_free (suggested_name);
2969 g_object_unref (source_win);
2973 do_create_folder (GtkWindow *parent_window,
2974 TnyFolderStore *parent_folder,
2975 const gchar *suggested_name)
2978 gchar *folder_name = NULL;
2980 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2982 (gchar *) suggested_name,
2985 if (result == GTK_RESPONSE_ACCEPT) {
2986 ModestMailOperation *mail_op;
2988 mail_op = modest_mail_operation_new ((GObject *) parent_window);
2989 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2991 modest_mail_operation_create_folder (mail_op,
2993 (const gchar *) folder_name,
2994 do_create_folder_cb,
2996 g_object_unref (mail_op);
3001 create_folder_performer (gboolean canceled,
3003 GtkWindow *parent_window,
3004 TnyAccount *account,
3007 TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3009 if (canceled || err) {
3010 /* In memory full conditions we could get this error here */
3011 if (err && is_memory_full_error (err)) {
3012 modest_platform_information_banner ((GtkWidget *) parent_window,
3013 NULL, dgettext("ke-recv",
3014 "cerm_device_memory_full"));
3019 /* Run the new folder dialog */
3020 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3023 g_object_unref (parent_folder);
3027 modest_ui_actions_create_folder(GtkWidget *parent_window,
3028 GtkWidget *folder_view)
3030 TnyFolderStore *parent_folder;
3032 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3034 if (parent_folder) {
3035 /* The parent folder will be freed in the callback */
3036 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3039 create_folder_performer,
3045 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3047 GtkWidget *folder_view;
3049 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3051 folder_view = modest_main_window_get_child_widget (main_window,
3052 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3056 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3060 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3063 const GError *error = NULL;
3064 const gchar *message = NULL;
3066 /* Get error message */
3067 error = modest_mail_operation_get_error (mail_op);
3069 g_return_if_reached ();
3071 switch (error->code) {
3072 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
3073 message = _CS("ckdg_ib_folder_already_exists");
3076 message = _("emev_ib_ui_imap_unable_to_rename");
3079 /* We don't set a parent for the dialog because the dialog
3080 will be destroyed so the banner won't appear */
3081 modest_platform_information_banner (NULL, NULL, message);
3085 TnyFolderStore *folder;
3090 on_rename_folder_cb (ModestMailOperation *mail_op,
3091 TnyFolder *new_folder,
3094 ModestFolderView *folder_view;
3096 folder_view = MODEST_FOLDER_VIEW (user_data);
3097 /* Note that if the rename fails new_folder will be NULL */
3099 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3101 modest_folder_view_select_first_inbox_or_local (folder_view);
3106 on_rename_folder_performer (gboolean canceled,
3108 GtkWindow *parent_window,
3109 TnyAccount *account,
3112 ModestMailOperation *mail_op = NULL;
3113 GtkTreeSelection *sel = NULL;
3114 GtkWidget *folder_view = NULL;
3115 RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3117 if (canceled || err) {
3118 /* In memory full conditions we could get this error here */
3119 if (err && is_memory_full_error (err)) {
3120 modest_platform_information_banner ((GtkWidget *) parent_window,
3121 NULL, dgettext("ke-recv",
3122 "cerm_device_memory_full"));
3124 } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3126 folder_view = modest_main_window_get_child_widget (
3127 MODEST_MAIN_WINDOW (parent_window),
3128 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3131 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3132 modest_ui_actions_rename_folder_error_handler,
3133 parent_window, NULL);
3135 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3138 /* Clear the headers view */
3139 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3140 gtk_tree_selection_unselect_all (sel);
3142 /* Actually rename the folder */
3143 modest_mail_operation_rename_folder (mail_op,
3144 TNY_FOLDER (data->folder),
3145 (const gchar *) (data->new_name),
3146 on_rename_folder_cb,
3148 g_object_unref (mail_op);
3151 g_free (data->new_name);
3156 modest_ui_actions_on_rename_folder (GtkAction *action,
3157 ModestMainWindow *main_window)
3159 TnyFolderStore *folder;
3160 GtkWidget *folder_view;
3161 GtkWidget *header_view;
3163 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3165 folder_view = modest_main_window_get_child_widget (main_window,
3166 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3170 header_view = modest_main_window_get_child_widget (main_window,
3171 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3176 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3181 if (TNY_IS_FOLDER (folder)) {
3184 const gchar *current_name;
3185 TnyFolderStore *parent;
3186 gboolean do_rename = TRUE;
3188 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3189 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3190 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
3191 parent, current_name,
3193 g_object_unref (parent);
3195 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3198 RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3199 rename_folder_data->folder = folder;
3200 rename_folder_data->new_name = folder_name;
3201 modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3202 folder, on_rename_folder_performer, rename_folder_data);
3205 g_object_unref (folder);
3209 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3212 GObject *win = modest_mail_operation_get_source (mail_op);
3214 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3215 _("mail_in_ui_folder_delete_error"),
3217 g_object_unref (win);
3221 TnyFolderStore *folder;
3222 gboolean move_to_trash;
3226 on_delete_folder_cb (gboolean canceled,
3228 GtkWindow *parent_window,
3229 TnyAccount *account,
3232 DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3233 GtkWidget *folder_view;
3234 ModestMailOperation *mail_op;
3235 GtkTreeSelection *sel;
3237 if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3238 g_object_unref (G_OBJECT (info->folder));
3243 folder_view = modest_main_window_get_child_widget (
3244 MODEST_MAIN_WINDOW (parent_window),
3245 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3247 /* Unselect the folder before deleting it to free the headers */
3248 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3249 gtk_tree_selection_unselect_all (sel);
3251 /* Create the mail operation */
3253 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3254 modest_ui_actions_delete_folder_error_handler,
3257 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3259 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3261 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3263 g_object_unref (G_OBJECT (mail_op));
3264 g_object_unref (G_OBJECT (info->folder));
3269 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3271 TnyFolderStore *folder;
3272 GtkWidget *folder_view;
3276 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3278 folder_view = modest_main_window_get_child_widget (main_window,
3279 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3283 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3285 /* Show an error if it's an account */
3286 if (!TNY_IS_FOLDER (folder)) {
3287 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3288 _("mail_in_ui_folder_delete_error"),
3290 g_object_unref (G_OBJECT (folder));
3295 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
3296 tny_folder_get_name (TNY_FOLDER (folder)));
3297 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3298 (const gchar *) message);
3301 if (response == GTK_RESPONSE_OK) {
3302 DeleteFolderInfo *info;
3303 info = g_new0(DeleteFolderInfo, 1);
3304 info->folder = folder;
3305 info->move_to_trash = move_to_trash;
3306 g_object_ref (G_OBJECT (info->folder));
3307 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3308 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window),
3310 TNY_FOLDER_STORE (account),
3311 on_delete_folder_cb, info);
3312 g_object_unref (account);
3314 g_object_unref (G_OBJECT (folder));
3318 modest_ui_actions_on_delete_folder (GtkAction *action,
3319 ModestMainWindow *main_window)
3321 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3323 delete_folder (main_window, FALSE);
3327 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3329 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3331 delete_folder (main_window, TRUE);
3336 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3337 const gchar* server_account_name,
3342 ModestMainWindow *main_window)
3344 g_return_if_fail(server_account_name);
3345 gboolean completed = FALSE;
3347 /* Initalize output parameters: */
3354 #ifdef MODEST_PLATFORM_MAEMO
3355 /* Maemo uses a different (awkward) button order,
3356 * It should probably just use gtk_alternative_dialog_button_order ().
3358 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3361 _("mcen_bd_dialog_ok"),
3362 GTK_RESPONSE_ACCEPT,
3363 _("mcen_bd_dialog_cancel"),
3364 GTK_RESPONSE_REJECT,
3367 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3371 GTK_RESPONSE_REJECT,
3373 GTK_RESPONSE_ACCEPT,
3375 #endif /* MODEST_PLATFORM_MAEMO */
3377 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3379 gchar *server_name = modest_account_mgr_get_server_account_hostname (
3380 modest_runtime_get_account_mgr(), server_account_name);
3381 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3382 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3388 /* This causes a warning because the logical ID has no %s in it,
3389 * though the translation does, but there is not much we can do about that: */
3390 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3391 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3394 g_free (server_name);
3398 gchar *initial_username = modest_account_mgr_get_server_account_username (
3399 modest_runtime_get_account_mgr(), server_account_name);
3401 GtkWidget *entry_username = gtk_entry_new ();
3402 if (initial_username)
3403 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3404 /* Dim this if a connection has ever succeeded with this username,
3405 * as per the UI spec: */
3406 const gboolean username_known =
3407 modest_account_mgr_get_server_account_username_has_succeeded(
3408 modest_runtime_get_account_mgr(), server_account_name);
3409 gtk_widget_set_sensitive (entry_username, !username_known);
3411 #ifdef MODEST_PLATFORM_MAEMO
3412 /* Auto-capitalization is the default, so let's turn it off: */
3413 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3415 /* Create a size group to be used by all captions.
3416 * Note that HildonCaption does not create a default size group if we do not specify one.
3417 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3418 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3420 GtkWidget *caption = hildon_caption_new (sizegroup,
3421 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3422 gtk_widget_show (entry_username);
3423 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3424 FALSE, FALSE, MODEST_MARGIN_HALF);
3425 gtk_widget_show (caption);
3427 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3429 #endif /* MODEST_PLATFORM_MAEMO */
3432 GtkWidget *entry_password = gtk_entry_new ();
3433 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3434 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3436 #ifdef MODEST_PLATFORM_MAEMO
3437 /* Auto-capitalization is the default, so let's turn it off: */
3438 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3439 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3441 caption = hildon_caption_new (sizegroup,
3442 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3443 gtk_widget_show (entry_password);
3444 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3445 FALSE, FALSE, MODEST_MARGIN_HALF);
3446 gtk_widget_show (caption);
3447 g_object_unref (sizegroup);
3449 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3451 #endif /* MODEST_PLATFORM_MAEMO */
3453 if (initial_username != NULL)
3454 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3456 /* This is not in the Maemo UI spec:
3457 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3458 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3462 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3464 while (!completed) {
3466 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3468 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3470 /* Note that an empty field becomes the "" string */
3471 if (*username && strlen (*username) > 0) {
3472 modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3473 server_account_name,
3477 const gboolean username_was_changed =
3478 (strcmp (*username, initial_username) != 0);
3479 if (username_was_changed) {
3480 g_warning ("%s: tinymail does not yet support changing the "
3481 "username in the get_password() callback.\n", __FUNCTION__);
3485 modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3486 _("mcen_ib_username_pw_incorrect"));
3492 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3494 /* We do not save the password in the configuration,
3495 * because this function is only called for passwords that should
3496 * not be remembered:
3497 modest_server_account_set_password (
3498 modest_runtime_get_account_mgr(), server_account_name,
3505 /* Set parent to NULL or the banner will disappear with its parent dialog */
3506 modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3517 /* This is not in the Maemo UI spec:
3518 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3524 gtk_widget_destroy (dialog);
3526 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3530 modest_ui_actions_on_cut (GtkAction *action,
3531 ModestWindow *window)
3533 GtkWidget *focused_widget;
3534 GtkClipboard *clipboard;
3536 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3537 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3538 if (GTK_IS_EDITABLE (focused_widget)) {
3539 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3540 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3541 gtk_clipboard_store (clipboard);
3542 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3543 GtkTextBuffer *buffer;
3545 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3546 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3547 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3548 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3549 gtk_clipboard_store (clipboard);
3551 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3552 TnyList *header_list = modest_header_view_get_selected_headers (
3553 MODEST_HEADER_VIEW (focused_widget));
3554 gboolean continue_download = FALSE;
3555 gint num_of_unc_msgs;
3557 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3559 if (num_of_unc_msgs) {
3560 TnyAccount *account = get_account_from_header_list (header_list);
3562 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3563 g_object_unref (account);
3567 if (num_of_unc_msgs == 0 || continue_download) {
3568 /* modest_platform_information_banner (
3569 NULL, NULL, _CS("mcen_ib_getting_items"));*/
3570 modest_header_view_cut_selection (
3571 MODEST_HEADER_VIEW (focused_widget));
3574 g_object_unref (header_list);
3575 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3576 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3581 modest_ui_actions_on_copy (GtkAction *action,
3582 ModestWindow *window)
3584 GtkClipboard *clipboard;
3585 GtkWidget *focused_widget;
3586 gboolean copied = TRUE;
3588 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3589 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3591 if (GTK_IS_LABEL (focused_widget)) {
3593 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3594 gtk_clipboard_set_text (clipboard, selection, -1);
3596 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3597 gtk_clipboard_store (clipboard);
3598 } else if (GTK_IS_EDITABLE (focused_widget)) {
3599 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3600 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3601 gtk_clipboard_store (clipboard);
3602 } else if (GTK_IS_HTML (focused_widget)) {
3603 gtk_html_copy (GTK_HTML (focused_widget));
3604 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3605 gtk_clipboard_store (clipboard);
3606 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3607 GtkTextBuffer *buffer;
3608 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3609 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3610 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3611 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3612 gtk_clipboard_store (clipboard);
3614 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3615 TnyList *header_list = modest_header_view_get_selected_headers (
3616 MODEST_HEADER_VIEW (focused_widget));
3617 gboolean continue_download = FALSE;
3618 gint num_of_unc_msgs;
3620 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3622 if (num_of_unc_msgs) {
3623 TnyAccount *account = get_account_from_header_list (header_list);
3625 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3626 g_object_unref (account);
3630 if (num_of_unc_msgs == 0 || continue_download) {
3631 modest_platform_information_banner (
3632 NULL, NULL, _CS("mcen_ib_getting_items"));
3633 modest_header_view_copy_selection (
3634 MODEST_HEADER_VIEW (focused_widget));
3638 g_object_unref (header_list);
3640 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3641 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3644 /* Show information banner if there was a copy to clipboard */
3646 modest_platform_information_banner (
3647 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3651 modest_ui_actions_on_undo (GtkAction *action,
3652 ModestWindow *window)
3654 ModestEmailClipboard *clipboard = NULL;
3656 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3657 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3658 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3659 /* Clear clipboard source */
3660 clipboard = modest_runtime_get_email_clipboard ();
3661 modest_email_clipboard_clear (clipboard);
3664 g_return_if_reached ();
3669 modest_ui_actions_on_redo (GtkAction *action,
3670 ModestWindow *window)
3672 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3673 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3676 g_return_if_reached ();
3682 destroy_information_note (ModestMailOperation *mail_op,
3685 /* destroy information note */
3686 gtk_widget_destroy (GTK_WIDGET(user_data));
3690 destroy_folder_information_note (ModestMailOperation *mail_op,
3691 TnyFolder *new_folder,
3694 /* destroy information note */
3695 gtk_widget_destroy (GTK_WIDGET(user_data));
3700 paste_as_attachment_free (gpointer data)
3702 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3704 gtk_widget_destroy (helper->banner);
3705 g_object_unref (helper->banner);
3710 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3715 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3721 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3726 modest_ui_actions_on_paste (GtkAction *action,
3727 ModestWindow *window)
3729 GtkWidget *focused_widget = NULL;
3730 GtkWidget *inf_note = NULL;
3731 ModestMailOperation *mail_op = NULL;
3733 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3734 if (GTK_IS_EDITABLE (focused_widget)) {
3735 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3736 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3737 ModestEmailClipboard *e_clipboard = NULL;
3738 e_clipboard = modest_runtime_get_email_clipboard ();
3739 if (modest_email_clipboard_cleared (e_clipboard)) {
3740 GtkTextBuffer *buffer;
3741 GtkClipboard *clipboard;
3743 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3744 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3745 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3746 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3747 ModestMailOperation *mail_op;
3748 TnyFolder *src_folder;
3751 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3752 helper->window = MODEST_MSG_EDIT_WINDOW (window);
3753 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3754 _CS("ckct_nw_pasting"));
3755 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3756 mail_op = modest_mail_operation_new (G_OBJECT (window));
3757 if (helper->banner != NULL) {
3758 g_object_ref (G_OBJECT (helper->banner));
3759 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3760 gtk_widget_show (GTK_WIDGET (helper->banner));
3764 modest_mail_operation_get_msgs_full (mail_op,
3766 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3768 paste_as_attachment_free);
3771 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3772 ModestEmailClipboard *clipboard = NULL;
3773 TnyFolder *src_folder = NULL;
3774 TnyFolderStore *folder_store = NULL;
3775 TnyList *data = NULL;
3776 gboolean delete = FALSE;
3778 /* Check clipboard source */
3779 clipboard = modest_runtime_get_email_clipboard ();
3780 if (modest_email_clipboard_cleared (clipboard))
3783 /* Get elements to paste */
3784 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3786 /* Create a new mail operation */
3787 mail_op = modest_mail_operation_new (G_OBJECT(window));
3789 /* Get destination folder */
3790 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3792 /* transfer messages */
3796 /* Ask for user confirmation */
3798 modest_ui_actions_msgs_move_to_confirmation (window,
3799 TNY_FOLDER (folder_store),
3803 if (response == GTK_RESPONSE_OK) {
3804 /* Launch notification */
3805 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3806 _CS("ckct_nw_pasting"));
3807 if (inf_note != NULL) {
3808 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3809 gtk_widget_show (GTK_WIDGET(inf_note));
3812 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3813 modest_mail_operation_xfer_msgs (mail_op,
3815 TNY_FOLDER (folder_store),
3817 destroy_information_note,
3820 g_object_unref (mail_op);
3823 } else if (src_folder != NULL) {
3824 /* Launch notification */
3825 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3826 _CS("ckct_nw_pasting"));
3827 if (inf_note != NULL) {
3828 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3829 gtk_widget_show (GTK_WIDGET(inf_note));
3832 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3833 modest_mail_operation_xfer_folder (mail_op,
3837 destroy_folder_information_note,
3843 g_object_unref (data);
3844 if (src_folder != NULL)
3845 g_object_unref (src_folder);
3846 if (folder_store != NULL)
3847 g_object_unref (folder_store);
3853 modest_ui_actions_on_select_all (GtkAction *action,
3854 ModestWindow *window)
3856 GtkWidget *focused_widget;
3858 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3859 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3860 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3861 } else if (GTK_IS_LABEL (focused_widget)) {
3862 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3863 } else if (GTK_IS_EDITABLE (focused_widget)) {
3864 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3865 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3866 GtkTextBuffer *buffer;
3867 GtkTextIter start, end;
3869 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3870 gtk_text_buffer_get_start_iter (buffer, &start);
3871 gtk_text_buffer_get_end_iter (buffer, &end);
3872 gtk_text_buffer_select_range (buffer, &start, &end);
3873 } else if (GTK_IS_HTML (focused_widget)) {
3874 gtk_html_select_all (GTK_HTML (focused_widget));
3875 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3876 GtkWidget *header_view = focused_widget;
3877 GtkTreeSelection *selection = NULL;
3879 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3880 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3881 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3884 /* Disable window dimming management */
3885 modest_window_disable_dimming (MODEST_WINDOW(window));
3887 /* Select all messages */
3888 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3889 gtk_tree_selection_select_all (selection);
3891 /* Set focuse on header view */
3892 gtk_widget_grab_focus (header_view);
3895 /* Enable window dimming management */
3896 modest_window_enable_dimming (MODEST_WINDOW(window));
3897 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3903 modest_ui_actions_on_mark_as_read (GtkAction *action,
3904 ModestWindow *window)
3906 g_return_if_fail (MODEST_IS_WINDOW(window));
3908 /* Mark each header as read */
3909 do_headers_action (window, headers_action_mark_as_read, NULL);
3913 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3914 ModestWindow *window)
3916 g_return_if_fail (MODEST_IS_WINDOW(window));
3918 /* Mark each header as read */
3919 do_headers_action (window, headers_action_mark_as_unread, NULL);
3923 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3924 GtkRadioAction *selected,
3925 ModestWindow *window)
3929 value = gtk_radio_action_get_current_value (selected);
3930 if (MODEST_IS_WINDOW (window)) {
3931 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3936 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3937 GtkRadioAction *selected,
3938 ModestWindow *window)
3940 TnyHeaderFlags flags;
3941 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3943 flags = gtk_radio_action_get_current_value (selected);
3944 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3948 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3949 GtkRadioAction *selected,
3950 ModestWindow *window)
3954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3956 file_format = gtk_radio_action_get_current_value (selected);
3957 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3962 modest_ui_actions_on_zoom_plus (GtkAction *action,
3963 ModestWindow *window)
3965 g_return_if_fail (MODEST_IS_WINDOW (window));
3967 modest_window_zoom_plus (MODEST_WINDOW (window));
3971 modest_ui_actions_on_zoom_minus (GtkAction *action,
3972 ModestWindow *window)
3974 g_return_if_fail (MODEST_IS_WINDOW (window));
3976 modest_window_zoom_minus (MODEST_WINDOW (window));
3980 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
3981 ModestWindow *window)
3983 ModestWindowMgr *mgr;
3984 gboolean fullscreen, active;
3985 g_return_if_fail (MODEST_IS_WINDOW (window));
3987 mgr = modest_runtime_get_window_mgr ();
3989 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3990 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3992 if (active != fullscreen) {
3993 modest_window_mgr_set_fullscreen_mode (mgr, active);
3994 gtk_window_present (GTK_WINDOW (window));
3999 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4000 ModestWindow *window)
4002 ModestWindowMgr *mgr;
4003 gboolean fullscreen;
4005 g_return_if_fail (MODEST_IS_WINDOW (window));
4007 mgr = modest_runtime_get_window_mgr ();
4008 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4009 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4011 gtk_window_present (GTK_WINDOW (window));
4015 * Used by modest_ui_actions_on_details to call do_headers_action
4018 headers_action_show_details (TnyHeader *header,
4019 ModestWindow *window,
4026 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4029 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4030 gtk_widget_show_all (dialog);
4031 gtk_dialog_run (GTK_DIALOG (dialog));
4033 gtk_widget_destroy (dialog);
4037 * Show the folder details in a ModestDetailsDialog widget
4040 show_folder_details (TnyFolder *folder,
4046 dialog = modest_details_dialog_new_with_folder (window, folder);
4049 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4050 gtk_widget_show_all (dialog);
4051 gtk_dialog_run (GTK_DIALOG (dialog));
4053 gtk_widget_destroy (dialog);
4057 * Show the header details in a ModestDetailsDialog widget
4060 modest_ui_actions_on_details (GtkAction *action,
4063 TnyList * headers_list;
4067 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4070 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4073 g_object_unref (msg);
4075 headers_list = get_selected_headers (win);
4079 iter = tny_list_create_iterator (headers_list);
4081 header = TNY_HEADER (tny_iterator_get_current (iter));
4083 headers_action_show_details (header, win, NULL);
4084 g_object_unref (header);
4087 g_object_unref (iter);
4088 g_object_unref (headers_list);
4090 } else if (MODEST_IS_MAIN_WINDOW (win)) {
4091 GtkWidget *folder_view, *header_view;
4093 /* Check which widget has the focus */
4094 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4095 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4096 if (gtk_widget_is_focus (folder_view)) {
4097 TnyFolderStore *folder_store
4098 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4099 if (!folder_store) {
4100 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4103 /* Show only when it's a folder */
4104 /* This function should not be called for account items,
4105 * because we dim the menu item for them. */
4106 if (TNY_IS_FOLDER (folder_store)) {
4107 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4110 g_object_unref (folder_store);
4113 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4114 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4115 /* Show details of each header */
4116 do_headers_action (win, headers_action_show_details, header_view);
4122 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4123 ModestMsgEditWindow *window)
4125 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4127 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4131 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4132 ModestMsgEditWindow *window)
4134 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4136 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4140 modest_ui_actions_toggle_folders_view (GtkAction *action,
4141 ModestMainWindow *main_window)
4143 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4145 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4146 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4148 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4152 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4153 ModestWindow *window)
4155 gboolean active, fullscreen = FALSE;
4156 ModestWindowMgr *mgr;
4158 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4160 /* Check if we want to toggle the toolbar vuew in fullscreen
4162 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4163 "ViewShowToolbarFullScreen")) {
4167 /* Toggle toolbar */
4168 mgr = modest_runtime_get_window_mgr ();
4169 modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4173 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4174 ModestMsgEditWindow *window)
4176 modest_msg_edit_window_select_font (window);
4181 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4182 const gchar *display_name,
4185 /* don't update the display name if it was already set;
4186 * updating the display name apparently is expensive */
4187 const gchar* old_name = gtk_window_get_title (window);
4189 if (display_name == NULL)
4192 if (old_name && display_name && strcmp (old_name, display_name) == 0)
4193 return; /* don't do anything */
4195 /* This is usually used to change the title of the main window, which
4196 * is the one that holds the folder view. Note that this change can
4197 * happen even when the widget doesn't have the focus. */
4198 gtk_window_set_title (window, display_name);
4203 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4205 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4206 modest_msg_edit_window_select_contacts (window);
4210 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4212 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4213 modest_msg_edit_window_check_names (window, FALSE);
4217 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4219 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4220 GTK_WIDGET (user_data));
4224 * This function is used to track changes in the selection of the
4225 * folder view that is inside the "move to" dialog to enable/disable
4226 * the OK button because we do not want the user to select a disallowed
4227 * destination for a folder.
4228 * The user also not desired to be able to use NEW button on items where
4229 * folder creation is not possibel.
4232 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4233 TnyFolderStore *folder_store,
4237 GtkWidget *dialog = NULL;
4238 GtkWidget *ok_button = NULL, *new_button = NULL;
4239 GList *children = NULL;
4240 gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4241 gboolean moving_folder = FALSE;
4242 gboolean is_local_account = TRUE;
4243 GtkWidget *folder_view = NULL;
4244 ModestTnyFolderRules rules;
4246 g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4251 /* Get the OK button */
4252 dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4256 children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4257 ok_button = GTK_WIDGET (children->next->next->data);
4258 new_button = GTK_WIDGET (children->next->data);
4259 g_list_free (children);
4261 /* check if folder_store is an remote account */
4262 if (TNY_IS_ACCOUNT (folder_store)) {
4263 TnyAccount *local_account = NULL;
4264 TnyAccount *mmc_account = NULL;
4265 ModestTnyAccountStore *account_store = NULL;
4267 account_store = modest_runtime_get_account_store ();
4268 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4269 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4271 if ((gpointer) local_account != (gpointer) folder_store &&
4272 (gpointer) mmc_account != (gpointer) folder_store) {
4273 const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4274 ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4275 if (proto_name != NULL) {
4276 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4278 is_local_account = FALSE;
4279 /* New button should be dimmed on remote
4281 new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4283 g_object_unref (local_account);
4284 g_object_unref (mmc_account);
4287 /* Check the target folder rules */
4288 if (TNY_IS_FOLDER (folder_store)) {
4289 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4290 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4291 ok_sensitive = FALSE;
4292 new_sensitive = FALSE;
4297 /* Check if we're moving a folder */
4298 if (MODEST_IS_MAIN_WINDOW (user_data)) {
4299 /* Get the widgets */
4300 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4301 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4302 if (gtk_widget_is_focus (folder_view))
4303 moving_folder = TRUE;
4306 if (moving_folder) {
4307 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4309 /* Get the folder to move */
4310 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4312 /* Check that we're not moving to the same folder */
4313 if (TNY_IS_FOLDER (moved_folder)) {
4314 parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4315 if (parent == folder_store)
4316 ok_sensitive = FALSE;
4317 g_object_unref (parent);
4320 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4321 /* Do not allow to move to an account unless it's the
4322 local folders account */
4323 if (!is_local_account)
4324 ok_sensitive = FALSE;
4327 if (ok_sensitive && (moved_folder == folder_store)) {
4328 /* Do not allow to move to itself */
4329 ok_sensitive = FALSE;
4331 g_object_unref (moved_folder);
4333 TnyFolder *src_folder = NULL;
4335 /* Moving a message */
4336 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4338 TnyHeader *header = NULL;
4339 header = modest_msg_view_window_get_header
4340 (MODEST_MSG_VIEW_WINDOW (user_data));
4341 if (!TNY_IS_HEADER(header))
4342 g_warning ("%s: could not get source header", __FUNCTION__);
4344 src_folder = tny_header_get_folder (header);
4347 g_object_unref (header);
4350 TNY_FOLDER (modest_folder_view_get_selected
4351 (MODEST_FOLDER_VIEW (folder_view)));
4354 if (TNY_IS_FOLDER(src_folder)) {
4355 /* Do not allow to move the msg to the same folder */
4356 /* Do not allow to move the msg to an account */
4357 if ((gpointer) src_folder == (gpointer) folder_store ||
4358 TNY_IS_ACCOUNT (folder_store))
4359 ok_sensitive = FALSE;
4360 g_object_unref (src_folder);
4362 g_warning ("%s: could not get source folder", __FUNCTION__);
4366 /* Set sensitivity of the OK button */
4367 gtk_widget_set_sensitive (ok_button, ok_sensitive);
4368 /* Set sensitivity of the NEW button */
4369 gtk_widget_set_sensitive (new_button, new_sensitive);
4373 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4376 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4378 return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4379 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4383 create_move_to_dialog (GtkWindow *win,
4384 GtkWidget *folder_view,
4385 GtkWidget **tree_view)
4387 GtkWidget *dialog, *scroll;
4388 GtkWidget *new_button;
4390 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4392 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4395 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4396 /* We do this manually so GTK+ does not associate a response ID for
4398 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4399 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4400 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4402 /* Create scrolled window */
4403 scroll = gtk_scrolled_window_new (NULL, NULL);
4404 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
4405 GTK_POLICY_AUTOMATIC,
4406 GTK_POLICY_AUTOMATIC);
4408 /* Create folder view */
4409 *tree_view = modest_platform_create_folder_view (NULL);
4411 /* Track changes in the selection to
4412 * disable the OK button whenever "Move to" is not possible
4413 * disbale NEW button whenever New is not possible */
4414 g_signal_connect (*tree_view,
4415 "folder_selection_changed",
4416 G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4419 /* Listen to clicks on New button */
4420 g_signal_connect (G_OBJECT (new_button),
4422 G_CALLBACK(create_move_to_dialog_on_new_folder),
4425 /* It could happen that we're trying to move a message from a
4426 window (msg window for example) after the main window was
4427 closed, so we can not just get the model of the folder
4429 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4430 const gchar *visible_id = NULL;
4432 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4433 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4434 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4435 MODEST_FOLDER_VIEW(*tree_view));
4438 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4440 /* Show the same account than the one that is shown in the main window */
4441 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
4444 const gchar *active_account_name = NULL;
4445 ModestAccountMgr *mgr = NULL;
4446 ModestAccountSettings *settings = NULL;
4447 ModestServerAccountSettings *store_settings = NULL;
4449 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4450 MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4451 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
4452 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4454 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4455 mgr = modest_runtime_get_account_mgr ();
4456 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4459 const gchar *store_account_name;
4460 store_settings = modest_account_settings_get_store_settings (settings);
4461 store_account_name = modest_server_account_settings_get_account_name (store_settings);
4463 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4464 store_account_name);
4465 g_object_unref (store_settings);
4466 g_object_unref (settings);
4470 /* we keep a pointer to the embedded folder view, so we can retrieve it with
4471 * get_folder_view_from_move_to_dialog
4472 * (see above) later (needed for focus handling)
4474 g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4477 /* Hide special folders */
4478 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4480 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4482 /* Add scroll to dialog */
4483 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
4484 scroll, TRUE, TRUE, 0);
4486 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4487 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4495 * Shows a confirmation dialog to the user when we're moving messages
4496 * from a remote server to the local storage. Returns the dialog
4497 * response. If it's other kind of movement then it always returns
4500 * This one is used by the next functions:
4501 * modest_ui_actions_on_paste - commented out
4502 * drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4505 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4506 TnyFolder *dest_folder,
4510 gint response = GTK_RESPONSE_OK;
4511 TnyAccount *account = NULL;
4512 TnyFolder *src_folder = NULL;
4513 TnyIterator *iter = NULL;
4514 TnyHeader *header = NULL;
4516 /* return with OK if the destination is a remote folder */
4517 if (modest_tny_folder_is_remote_folder (dest_folder))
4518 return GTK_RESPONSE_OK;
4520 /* Get source folder */
4521 iter = tny_list_create_iterator (headers);
4522 header = TNY_HEADER (tny_iterator_get_current (iter));
4524 src_folder = tny_header_get_folder (header);
4525 g_object_unref (header);
4527 g_object_unref (iter);
4529 /* if no src_folder, message may be an attahcment */
4530 if (src_folder == NULL)
4531 return GTK_RESPONSE_CANCEL;
4533 /* If the source is a local or MMC folder */
4534 if (!modest_tny_folder_is_remote_folder (src_folder)) {
4535 g_object_unref (src_folder);
4536 return GTK_RESPONSE_OK;
4539 /* Get the account */
4540 account = tny_folder_get_account (src_folder);
4542 /* now if offline we ask the user */
4543 if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4544 response = GTK_RESPONSE_OK;
4546 response = GTK_RESPONSE_CANCEL;
4549 g_object_unref (src_folder);
4550 g_object_unref (account);
4556 move_to_cb (ModestMailOperation *mail_op,
4559 MoveToHelper *helper = (MoveToHelper *) user_data;
4561 /* Note that the operation could have failed, in that case do
4563 if (modest_mail_operation_get_status (mail_op) ==
4564 MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4566 GObject *object = modest_mail_operation_get_source (mail_op);
4567 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4568 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4570 if (!modest_msg_view_window_select_next_message (self) &&
4571 !modest_msg_view_window_select_previous_message (self)) {
4572 /* No more messages to view, so close this window */
4573 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4575 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4576 GtkWidget *header_view;
4578 GtkTreeSelection *sel;
4580 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4581 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4582 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4583 path = gtk_tree_row_reference_get_path (helper->reference);
4584 /* We need to unselect the previous one
4585 because we could be copying instead of
4587 gtk_tree_selection_unselect_all (sel);
4588 gtk_tree_selection_select_path (sel, path);
4589 gtk_tree_path_free (path);
4591 g_object_unref (object);
4594 /* Close the "Pasting" information banner */
4595 gtk_widget_destroy (GTK_WIDGET(helper->banner));
4596 g_object_unref (helper->banner);
4597 if (helper->reference != NULL)
4598 gtk_tree_row_reference_free (helper->reference);
4603 folder_move_to_cb (ModestMailOperation *mail_op,
4604 TnyFolder *new_folder,
4607 GtkWidget *folder_view;
4610 object = modest_mail_operation_get_source (mail_op);
4611 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4612 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4613 g_object_ref (folder_view);
4614 g_object_unref (object);
4615 move_to_cb (mail_op, user_data);
4616 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4617 g_object_unref (folder_view);
4621 msgs_move_to_cb (ModestMailOperation *mail_op,
4624 move_to_cb (mail_op, user_data);
4628 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4631 ModestWindow *main_window = NULL;
4633 /* Disable next automatic folder selection */
4634 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4635 FALSE); /* don't create */
4637 GObject *win = NULL;
4638 GtkWidget *folder_view = NULL;
4640 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4641 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4642 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4644 if (user_data && TNY_IS_FOLDER (user_data)) {
4645 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
4646 TNY_FOLDER (user_data), FALSE);
4649 /* Show notification dialog only if the main window exists */
4650 win = modest_mail_operation_get_source (mail_op);
4651 modest_platform_run_information_dialog ((GtkWindow *) win,
4652 _("mail_in_ui_folder_move_target_error"),
4655 g_object_unref (win);
4660 open_msg_for_purge_cb (ModestMailOperation *mail_op,
4669 gint pending_purges = 0;
4670 gboolean some_purged = FALSE;
4671 ModestWindow *win = MODEST_WINDOW (user_data);
4672 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4674 /* If there was any error */
4675 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4676 modest_window_mgr_unregister_header (mgr, header);
4680 /* Once the message has been retrieved for purging, we check if
4681 * it's all ok for purging */
4683 parts = tny_simple_list_new ();
4684 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4685 iter = tny_list_create_iterator (parts);
4687 while (!tny_iterator_is_done (iter)) {
4689 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4690 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4691 if (tny_mime_part_is_purged (part))
4698 g_object_unref (part);
4700 tny_iterator_next (iter);
4702 g_object_unref (iter);
4705 if (pending_purges>0) {
4707 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4709 if (response == GTK_RESPONSE_OK) {
4710 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4711 iter = tny_list_create_iterator (parts);
4712 while (!tny_iterator_is_done (iter)) {
4715 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4716 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4717 tny_mime_part_set_purged (part);
4720 g_object_unref (part);
4722 tny_iterator_next (iter);
4724 g_object_unref (iter);
4726 tny_msg_rewrite_cache (msg);
4729 /* This string no longer exists, refer to NB#75415 for more info */
4730 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4733 modest_window_mgr_unregister_header (mgr, header);
4735 g_object_unref (parts);
4739 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4740 ModestMainWindow *win)
4742 GtkWidget *header_view;
4743 TnyList *header_list;
4745 TnyHeaderFlags flags;
4746 ModestWindow *msg_view_window = NULL;
4749 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4751 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4752 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4754 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4756 g_warning ("%s: no header selected", __FUNCTION__);
4760 if (tny_list_get_length (header_list) == 1) {
4761 TnyIterator *iter = tny_list_create_iterator (header_list);
4762 header = TNY_HEADER (tny_iterator_get_current (iter));
4763 g_object_unref (iter);
4767 if (!header || !TNY_IS_HEADER(header)) {
4768 g_warning ("%s: header is not valid", __FUNCTION__);
4772 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4773 header, &msg_view_window);
4774 flags = tny_header_get_flags (header);
4775 if (!(flags & TNY_HEADER_FLAG_CACHED))
4778 if (msg_view_window != NULL)
4779 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4781 /* do nothing; uid was registered before, so window is probably on it's way */
4782 g_warning ("debug: header %p has already been registered", header);
4785 ModestMailOperation *mail_op = NULL;
4786 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4787 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4788 modest_ui_actions_disk_operations_error_handler,
4790 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4791 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4793 g_object_unref (mail_op);
4796 g_object_unref (header);
4798 g_object_unref (header_list);
4802 * Checks if we need a connection to do the transfer and if the user
4803 * wants to connect to complete it
4806 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4807 TnyFolderStore *src_folder,
4809 TnyFolder *dst_folder,
4810 gboolean delete_originals,
4811 gboolean *need_connection,
4814 TnyAccount *src_account;
4815 gint uncached_msgs = 0;
4817 uncached_msgs = header_list_count_uncached_msgs (headers);
4819 /* We don't need any further check if
4821 * 1- the source folder is local OR
4822 * 2- the device is already online
4824 if (!modest_tny_folder_store_is_remote (src_folder) ||
4825 tny_device_is_online (modest_runtime_get_device())) {
4826 *need_connection = FALSE;
4831 /* We must ask for a connection when
4833 * - the message(s) is not already cached OR
4834 * - the message(s) is cached but the leave_on_server setting
4835 * is FALSE (because we need to sync the source folder to
4836 * delete the message from the server (for IMAP we could do it
4837 * offline, it'll take place the next time we get a
4840 src_account = get_account_from_folder_store (src_folder);
4841 if (uncached_msgs > 0) {
4845 *need_connection = TRUE;
4846 num_headers = tny_list_get_length (headers);
4847 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4849 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4850 GTK_RESPONSE_CANCEL) {
4856 /* The transfer is possible and the user wants to */
4859 if (remote_folder_is_pop (src_folder) && delete_originals) {
4860 const gchar *account_name;
4861 gboolean leave_on_server;
4863 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4864 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4867 if (leave_on_server == TRUE) {
4868 *need_connection = FALSE;
4870 *need_connection = TRUE;
4873 *need_connection = FALSE;
4878 g_object_unref (src_account);
4882 xfer_messages_error_handler (ModestMailOperation *mail_op,
4885 ModestWindow *main_window = NULL;
4887 /* Disable next automatic folder selection */
4888 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4889 FALSE); /* don't create */
4891 GObject *win = modest_mail_operation_get_source (mail_op);
4892 modest_platform_run_information_dialog ((GtkWindow *) win,
4893 _("mail_in_ui_folder_move_target_error"),
4896 g_object_unref (win);
4901 * Utility function that transfer messages from both the main window
4902 * and the msg view window when using the "Move to" dialog
4905 xfer_messages_performer (gboolean canceled,
4907 GtkWindow *parent_window,
4908 TnyAccount *account,
4911 TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4912 ModestWindow *win = MODEST_WINDOW (parent_window);
4913 TnyList *headers = NULL;
4914 TnyAccount *dst_account = NULL;
4915 const gchar *proto_str = NULL;
4916 gboolean dst_is_pop = FALSE;
4922 if (is_memory_full_error (err)) {
4923 modest_platform_information_banner ((GtkWidget *) parent_window,
4924 NULL, dgettext("ke-recv",
4925 "cerm_device_memory_full"));
4927 /* Show the proper error message */
4928 modest_ui_actions_on_account_connection_error (parent_window, account);
4933 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4934 proto_str = tny_account_get_proto (dst_account);
4936 /* tinymail will return NULL for local folders it seems */
4937 dst_is_pop = proto_str &&
4938 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
4939 MODEST_PROTOCOL_STORE_POP);
4941 g_object_unref (dst_account);
4943 /* Get selected headers */
4944 headers = get_selected_headers (MODEST_WINDOW (win));
4946 g_warning ("%s: no headers selected", __FUNCTION__);
4952 modest_platform_information_banner (GTK_WIDGET (win),
4954 ngettext("mail_in_ui_folder_move_target_error",
4955 "mail_in_ui_folder_move_targets_error",
4956 tny_list_get_length (headers)));
4957 g_object_unref (headers);
4961 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4962 helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4963 _CS("ckct_nw_pasting"));
4964 if (helper->banner != NULL) {
4965 g_object_ref (helper->banner);
4966 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4967 gtk_widget_show (GTK_WIDGET(helper->banner));
4970 if (MODEST_IS_MAIN_WINDOW (win)) {
4971 GtkWidget *header_view =
4972 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4973 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4974 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4977 ModestMailOperation *mail_op =
4978 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4979 xfer_messages_error_handler,
4981 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4984 modest_mail_operation_xfer_msgs (mail_op,
4986 TNY_FOLDER (dst_folder),
4991 g_object_unref (G_OBJECT (mail_op));
4992 g_object_unref (headers);
4994 g_object_unref (dst_folder);
4998 TnyFolder *src_folder;
4999 TnyFolderStore *dst_folder;
5000 gboolean delete_original;
5001 GtkWidget *folder_view;
5005 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5006 TnyAccount *account, gpointer user_data)
5008 MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5009 GtkTreeSelection *sel;
5010 ModestMailOperation *mail_op = NULL;
5012 if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5013 g_object_unref (G_OBJECT (info->src_folder));
5014 g_object_unref (G_OBJECT (info->dst_folder));
5019 MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5020 helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5021 _CS("ckct_nw_pasting"));
5022 if (helper->banner != NULL) {
5023 g_object_ref (helper->banner);
5024 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
5025 gtk_widget_show (GTK_WIDGET(helper->banner));
5027 /* Clean folder on header view before moving it */
5028 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5029 gtk_tree_selection_unselect_all (sel);
5031 /* Let gtk events run. We need that the folder
5032 view frees its reference to the source
5033 folder *before* issuing the mail operation
5034 so we need the signal handler of selection
5035 changed to happen before the mail
5037 while (gtk_events_pending ())
5038 gtk_main_iteration (); */
5041 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5042 modest_ui_actions_move_folder_error_handler,
5043 info->src_folder, NULL);
5044 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5047 /* Select *after* the changes */
5048 /* TODO: this function hangs UI after transfer */
5049 /* modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5050 /* TNY_FOLDER (src_folder), TRUE); */
5052 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5053 TNY_FOLDER (info->dst_folder), TRUE);
5054 modest_mail_operation_xfer_folder (mail_op,
5055 TNY_FOLDER (info->src_folder),
5057 info->delete_original,
5060 g_object_unref (G_OBJECT (info->src_folder));
5062 /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) { */
5065 /* Unref mail operation */
5066 g_object_unref (G_OBJECT (mail_op));
5067 g_object_unref (G_OBJECT (info->dst_folder));
5072 get_account_from_folder_store (TnyFolderStore *folder_store)
5074 if (TNY_IS_ACCOUNT (folder_store))
5075 return g_object_ref (folder_store);
5077 return tny_folder_get_account (TNY_FOLDER (folder_store));
5081 * UI handler for the "Move to" action when invoked from the
5085 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5086 GtkWidget *folder_view,
5087 TnyFolderStore *dst_folder,
5088 ModestMainWindow *win)
5090 ModestHeaderView *header_view = NULL;
5091 TnyFolderStore *src_folder = NULL;
5093 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5095 /* Get the source folder */
5096 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5098 /* Get header view */
5099 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5101 /* Get folder or messages to transfer */
5102 if (gtk_widget_is_focus (folder_view)) {
5103 gboolean do_xfer = TRUE;
5105 /* Allow only to transfer folders to the local root folder */
5106 if (TNY_IS_ACCOUNT (dst_folder) &&
5107 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5108 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5110 } else if (!TNY_IS_FOLDER (src_folder)) {
5111 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5116 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5117 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5119 info->src_folder = g_object_ref (src_folder);
5120 info->dst_folder = g_object_ref (dst_folder);
5121 info->delete_original = TRUE;
5122 info->folder_view = folder_view;
5124 connect_info->callback = on_move_folder_cb;
5125 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5126 connect_info->data = info;
5128 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5129 TNY_FOLDER_STORE (src_folder),
5132 } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5135 headers = modest_header_view_get_selected_headers(header_view);
5137 /* Transfer the messages */
5138 transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5139 headers, TNY_FOLDER (dst_folder));
5141 g_object_unref (headers);
5145 g_object_unref (src_folder);
5150 transfer_messages_helper (GtkWindow *win,
5151 TnyFolder *src_folder,
5153 TnyFolder *dst_folder)
5155 gboolean need_connection = TRUE;
5156 gboolean do_xfer = TRUE;
5158 modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5159 headers, TNY_FOLDER (dst_folder),
5160 TRUE, &need_connection,
5163 /* If we don't want to transfer just return */
5167 if (need_connection) {
5168 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5169 connect_info->callback = xfer_messages_performer;
5170 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5171 connect_info->data = g_object_ref (dst_folder);
5173 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5174 TNY_FOLDER_STORE (src_folder),
5177 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5178 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5180 g_object_ref (dst_folder));
5181 g_object_unref (src_account);
5186 * UI handler for the "Move to" action when invoked from the
5187 * ModestMsgViewWindow
5190 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
5191 TnyFolderStore *dst_folder,
5192 ModestMsgViewWindow *win)
5194 TnyList *headers = NULL;
5195 TnyHeader *header = NULL;
5196 TnyFolder *src_folder = NULL;
5198 g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5200 /* Create header list */
5201 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5202 src_folder = TNY_FOLDER (tny_header_get_folder(header));
5203 headers = tny_simple_list_new ();
5204 tny_list_append (headers, G_OBJECT (header));
5206 /* Transfer the messages */
5207 transfer_messages_helper (GTK_WINDOW (win), src_folder, headers,
5208 TNY_FOLDER (dst_folder));
5211 g_object_unref (header);
5212 g_object_unref (headers);
5216 modest_ui_actions_on_move_to (GtkAction *action,
5219 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5221 TnyFolderStore *dst_folder = NULL;
5222 ModestMainWindow *main_window;
5224 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5225 MODEST_IS_MSG_VIEW_WINDOW (win));
5227 /* Get the main window if exists */
5228 if (MODEST_IS_MAIN_WINDOW (win))
5229 main_window = MODEST_MAIN_WINDOW (win);
5232 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5233 FALSE)); /* don't create */
5235 /* Get the folder view widget if exists */
5237 folder_view = modest_main_window_get_child_widget (main_window,
5238 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5242 /* Create and run the dialog */
5243 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5244 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5245 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5246 result = gtk_dialog_run (GTK_DIALOG(dialog));
5247 g_object_ref (tree_view);
5248 gtk_widget_destroy (dialog);
5250 if (result != GTK_RESPONSE_ACCEPT)
5253 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5254 /* Do window specific stuff */
5255 if (MODEST_IS_MAIN_WINDOW (win)) {
5256 modest_ui_actions_on_main_window_move_to (action,
5259 MODEST_MAIN_WINDOW (win));
5261 modest_ui_actions_on_msg_view_window_move_to (action,
5263 MODEST_MSG_VIEW_WINDOW (win));
5267 g_object_unref (dst_folder);
5271 * Calls #HeadersFunc for each header already selected in the main
5272 * window or the message currently being shown in the msg view window
5275 do_headers_action (ModestWindow *win,
5279 TnyList *headers_list = NULL;
5280 TnyIterator *iter = NULL;
5281 TnyHeader *header = NULL;
5282 TnyFolder *folder = NULL;
5285 headers_list = get_selected_headers (win);
5289 /* Get the folder */
5290 iter = tny_list_create_iterator (headers_list);
5291 header = TNY_HEADER (tny_iterator_get_current (iter));
5293 folder = tny_header_get_folder (header);
5294 g_object_unref (header);
5297 /* Call the function for each header */
5298 while (!tny_iterator_is_done (iter)) {
5299 header = TNY_HEADER (tny_iterator_get_current (iter));
5300 func (header, win, user_data);
5301 g_object_unref (header);
5302 tny_iterator_next (iter);
5305 /* Trick: do a poke status in order to speed up the signaling
5307 tny_folder_poke_status (folder);
5310 g_object_unref (folder);
5311 g_object_unref (iter);
5312 g_object_unref (headers_list);
5316 modest_ui_actions_view_attachment (GtkAction *action,
5317 ModestWindow *window)
5319 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5320 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5322 /* not supported window for this action */
5323 g_return_if_reached ();
5328 modest_ui_actions_save_attachments (GtkAction *action,
5329 ModestWindow *window)
5331 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5333 if (modest_platform_check_memory_low (MODEST_WINDOW(window)))
5336 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5338 /* not supported window for this action */
5339 g_return_if_reached ();
5344 modest_ui_actions_remove_attachments (GtkAction *action,
5345 ModestWindow *window)
5347 if (MODEST_IS_MAIN_WINDOW (window)) {
5348 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5349 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5350 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5352 /* not supported window for this action */
5353 g_return_if_reached ();
5358 modest_ui_actions_on_settings (GtkAction *action,
5363 dialog = modest_platform_get_global_settings_dialog ();
5364 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5365 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5366 gtk_widget_show_all (dialog);
5368 gtk_dialog_run (GTK_DIALOG (dialog));
5370 gtk_widget_destroy (dialog);
5374 modest_ui_actions_on_help (GtkAction *action,
5377 const gchar *help_id;
5379 g_return_if_fail (action);
5380 g_return_if_fail (win && GTK_IS_WINDOW(win));
5382 help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5385 modest_platform_show_help (GTK_WINDOW (win), help_id);
5387 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5391 retrieve_msg_contents_performer (gboolean canceled,
5393 GtkWindow *parent_window,
5394 TnyAccount *account,
5397 ModestMailOperation *mail_op;
5398 TnyList *headers = TNY_LIST (user_data);
5400 if (err || canceled) {
5401 if (err && is_memory_full_error (err)) {
5402 modest_platform_information_banner ((GtkWidget *) parent_window,
5403 NULL, dgettext("ke-recv",
5404 "cerm_device_memory_full"));
5409 /* Create mail operation */
5410 mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5411 modest_ui_actions_disk_operations_error_handler,
5413 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5414 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5417 g_object_unref (mail_op);
5419 g_object_unref (headers);
5420 g_object_unref (account);
5424 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5425 ModestWindow *window)
5427 TnyList *headers = NULL;
5428 TnyAccount *account = NULL;
5429 TnyIterator *iter = NULL;
5430 TnyHeader *header = NULL;
5431 TnyFolder *folder = NULL;
5434 headers = get_selected_headers (window);
5438 /* Pick the account */
5439 iter = tny_list_create_iterator (headers);
5440 header = TNY_HEADER (tny_iterator_get_current (iter));
5441 folder = tny_header_get_folder (header);
5442 account = tny_folder_get_account (folder);
5443 g_object_unref (folder);
5444 g_object_unref (header);
5445 g_object_unref (iter);
5447 /* Connect and perform the message retrieval */
5448 modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5449 g_object_ref (account),
5450 retrieve_msg_contents_performer,
5451 g_object_ref (headers));
5454 g_object_unref (account);
5455 g_object_unref (headers);
5459 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5461 g_return_if_fail (MODEST_IS_WINDOW (window));
5464 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5468 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5470 g_return_if_fail (MODEST_IS_WINDOW (window));
5473 modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5477 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5478 ModestWindow *window)
5480 g_return_if_fail (MODEST_IS_WINDOW (window));
5483 modest_ui_actions_check_menu_dimming_rules (window);
5487 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5488 ModestWindow *window)
5490 g_return_if_fail (MODEST_IS_WINDOW (window));
5493 modest_ui_actions_check_menu_dimming_rules (window);
5497 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5498 ModestWindow *window)
5500 g_return_if_fail (MODEST_IS_WINDOW (window));
5503 modest_ui_actions_check_menu_dimming_rules (window);
5507 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5508 ModestWindow *window)
5510 g_return_if_fail (MODEST_IS_WINDOW (window));
5513 modest_ui_actions_check_menu_dimming_rules (window);
5517 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5518 ModestWindow *window)
5520 g_return_if_fail (MODEST_IS_WINDOW (window));
5523 modest_ui_actions_check_menu_dimming_rules (window);
5527 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5528 ModestWindow *window)
5530 g_return_if_fail (MODEST_IS_WINDOW (window));
5533 modest_ui_actions_check_menu_dimming_rules (window);
5537 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5538 ModestWindow *window)
5540 g_return_if_fail (MODEST_IS_WINDOW (window));
5543 modest_ui_actions_check_menu_dimming_rules (window);
5547 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5548 ModestWindow *window)
5550 g_return_if_fail (MODEST_IS_WINDOW (window));
5553 modest_ui_actions_check_menu_dimming_rules (window);
5557 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5558 ModestWindow *window)
5560 g_return_if_fail (MODEST_IS_WINDOW (window));
5563 modest_ui_actions_check_menu_dimming_rules (window);
5567 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5569 g_return_if_fail (MODEST_IS_WINDOW (window));
5571 /* we check for low-mem; in that case, show a warning, and don't allow
5574 if (modest_platform_check_memory_low (window))
5577 modest_platform_show_search_messages (GTK_WINDOW (window));
5581 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5583 g_return_if_fail (MODEST_IS_WINDOW (win));
5586 /* we check for low-mem; in that case, show a warning, and don't allow
5587 * for the addressbook
5589 if (modest_platform_check_memory_low (win))
5593 modest_platform_show_addressbook (GTK_WINDOW (win));
5598 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5599 ModestWindow *window)
5601 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5603 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5607 on_send_receive_finished (ModestMailOperation *mail_op,
5610 GtkWidget *header_view, *folder_view;
5611 TnyFolderStore *folder_store;
5612 ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5614 /* Set send/receive operation finished */
5615 modest_main_window_notify_send_receive_completed (main_win);
5617 /* Don't refresh the current folder if there were any errors */
5618 if (modest_mail_operation_get_status (mail_op) !=
5619 MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5622 /* Refresh the current folder if we're viewing a window. We do
5623 this because the user won't be able to see the new mails in
5624 the selected folder after a Send&Receive because it only
5625 performs a poke_status, i.e, only the number of read/unread
5626 messages is updated, but the new headers are not
5628 folder_view = modest_main_window_get_child_widget (main_win,
5629 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5633 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5635 /* Do not need to refresh INBOX again because the
5636 update_account does it always automatically */
5637 if (folder_store && TNY_IS_FOLDER (folder_store) &&
5638 tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5639 ModestMailOperation *refresh_op;
5641 header_view = modest_main_window_get_child_widget (main_win,
5642 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5644 /* We do not need to set the contents style
5645 because it hasn't changed. We also do not
5646 need to save the widget status. Just force
5648 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5649 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5650 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5651 folder_refreshed_cb, main_win);
5652 g_object_unref (refresh_op);
5656 g_object_unref (folder_store);
5661 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5667 const gchar* server_name = NULL;
5668 TnyTransportAccount *server_account;
5669 gchar *message = NULL;
5671 /* Don't show anything if the user cancelled something or the send receive request is not
5673 if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5674 !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5678 /* Get the server name: */
5680 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5682 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5684 g_return_if_reached ();
5686 /* Show the appropriate message text for the GError: */
5687 switch (err->code) {
5688 case TNY_SERVICE_ERROR_CONNECT:
5689 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5691 case TNY_SERVICE_ERROR_AUTHENTICATE:
5692 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5694 case TNY_SERVICE_ERROR_SEND:
5695 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5697 case TNY_SERVICE_ERROR_UNAVAILABLE:
5698 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5701 g_warning ("%s: unexpected ERROR %d",
5702 __FUNCTION__, err->code);
5703 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5707 /* TODO if the username or the password where not defined we
5708 should show the Accounts Settings dialog or the Connection
5709 specific SMTP server window */
5711 modest_platform_run_information_dialog (NULL, message, FALSE);
5713 g_object_unref (server_account);
5717 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5722 ModestMainWindow *main_window = NULL;
5723 ModestWindowMgr *mgr = NULL;
5724 GtkWidget *folder_view = NULL, *header_view = NULL;
5725 TnyFolderStore *selected_folder = NULL;
5726 TnyFolderType folder_type;
5728 mgr = modest_runtime_get_window_mgr ();
5729 main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5730 FALSE));/* don't create */
5734 /* Check if selected folder is OUTBOX */
5735 folder_view = modest_main_window_get_child_widget (main_window,
5736 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5737 header_view = modest_main_window_get_child_widget (main_window,
5738 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5740 selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5741 if (!TNY_IS_FOLDER (selected_folder))
5744 /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5745 #if GTK_CHECK_VERSION(2, 8, 0)
5746 folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder));
5747 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
5748 GtkTreeViewColumn *tree_column;
5750 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5751 TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5752 gtk_tree_view_column_queue_resize (tree_column);
5755 gtk_widget_queue_draw (header_view);
5758 /* Rerun dimming rules, because the message could become deletable for example */
5759 modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window),
5760 MODEST_DIMMING_RULES_TOOLBAR);
5764 if (selected_folder != NULL)
5765 g_object_unref (selected_folder);
5769 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5770 TnyAccount *account)
5772 ModestTransportStoreProtocol proto;
5773 const gchar *proto_name;
5774 gchar *error_note = NULL;
5776 proto_name = tny_account_get_proto (account);
5777 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5780 case MODEST_PROTOCOL_STORE_POP:
5781 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"),
5782 tny_account_get_hostname (account));
5784 case MODEST_PROTOCOL_STORE_IMAP:
5785 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"),
5786 tny_account_get_hostname (account));
5788 case MODEST_PROTOCOL_STORE_MAILDIR:
5789 case MODEST_PROTOCOL_STORE_MBOX:
5790 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5793 g_warning ("%s: This should not be reached", __FUNCTION__);
5797 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5798 g_free (error_note);
5803 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5806 TnyFolderStore *folder = NULL;
5807 TnyAccount *account = NULL;
5808 ModestTransportStoreProtocol proto;
5809 TnyHeader *header = NULL;
5811 if (MODEST_IS_MAIN_WINDOW (win)) {
5812 GtkWidget *header_view;
5813 TnyList* headers = NULL;
5815 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5816 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5817 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5818 if (!headers || tny_list_get_length (headers) == 0) {
5820 g_object_unref (headers);
5823 iter = tny_list_create_iterator (headers);
5824 header = TNY_HEADER (tny_iterator_get_current (iter));
5825 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5826 g_object_unref (iter);
5827 g_object_unref (headers);
5828 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5829 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5830 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5833 /* Get the account type */
5834 account = tny_folder_get_account (TNY_FOLDER (folder));
5835 proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5836 if (proto == MODEST_PROTOCOL_STORE_POP) {
5837 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5838 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5840 subject = tny_header_dup_subject (header);
5841 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
5845 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5849 g_object_unref (account);
5850 g_object_unref (folder);
5851 g_object_unref (header);