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"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
82 #include <gtkhtml/gtkhtml.h>
84 typedef struct _GetMsgAsyncHelper {
86 ModestMailOperation *mail_op;
93 typedef enum _ReplyForwardAction {
99 typedef struct _ReplyForwardHelper {
100 guint reply_forward_type;
101 ReplyForwardAction action;
103 GtkWidget *parent_window;
104 } ReplyForwardHelper;
106 typedef struct _PasteAsAttachmentHelper {
107 ModestMsgEditWindow *window;
109 } PasteAsAttachmentHelper;
113 * The do_headers_action uses this kind of functions to perform some
114 * action to each member of a list of headers
116 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
118 static void do_headers_action (ModestWindow *win,
122 static void open_msg_cb (ModestMailOperation *mail_op,
127 static void reply_forward_cb (ModestMailOperation *mail_op,
132 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
134 static void folder_refreshed_cb (ModestMailOperation *mail_op,
138 static void _on_send_receive_progress_changed (ModestMailOperation *mail_op,
139 ModestMailOperationState *state,
142 static gint header_list_count_uncached_msgs (
143 TnyList *header_list,
145 static gboolean download_uncached_messages (
147 gint num_of_uncached_msgs);
151 /* Show the account creation wizard dialog.
152 * returns: TRUE if an account was created. FALSE if the user cancelled.
155 modest_run_account_setup_wizard (ModestWindow *win)
157 gboolean result = FALSE;
160 wizard = modest_window_mgr_get_easysetup_dialog
161 (modest_runtime_get_window_mgr());
163 /* old wizard is active already; present it and
164 * act as if the user cancelled the non-existing
167 printf ("wizard already active\n");
170 /* there is no such wizard yet */
171 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
172 modest_window_mgr_set_easysetup_dialog
173 (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
177 /* always present a main window in the background
178 * we do it here, so we cannot end up with to wizards (as this
179 * function might be called in modest_window_mgr_get_main_window as well */
181 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
183 /* make sure the mainwindow is visible */
184 gtk_widget_show_all (GTK_WIDGET(win));
185 gtk_window_present (GTK_WINDOW(win));
188 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
190 /* Don't make this a modal window, because secondary windows will then
191 * be unusable, freezing the UI: */
192 /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
194 gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
195 if (dialog_response == GTK_RESPONSE_CANCEL)
198 /* Check whether an account was created: */
199 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
202 gtk_widget_destroy (GTK_WIDGET (wizard));
204 /* clear it from the window mgr */
205 modest_window_mgr_set_easysetup_dialog
206 (modest_runtime_get_window_mgr(), NULL);
213 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
216 const gchar *authors[] = {
217 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
220 about = gtk_about_dialog_new ();
221 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
222 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
223 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
224 _("Copyright (c) 2006, Nokia Corporation\n"
225 "All rights reserved."));
226 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
227 _("a modest e-mail client\n\n"
228 "design and implementation: Dirk-Jan C. Binnema\n"
229 "contributions from the fine people at KC and Ig\n"
230 "uses the tinymail email framework written by Philip van Hoof"));
231 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
232 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
233 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
234 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
236 gtk_dialog_run (GTK_DIALOG (about));
237 gtk_widget_destroy(about);
241 * Gets the list of currently selected messages. If the win is the
242 * main window, then it returns a newly allocated list of the headers
243 * selected in the header view. If win is the msg view window, then
244 * the value returned is a list with just a single header.
246 * The caller of this funcion must free the list.
249 get_selected_headers (ModestWindow *win)
251 if (MODEST_IS_MAIN_WINDOW(win)) {
252 GtkWidget *header_view;
254 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
255 MODEST_WIDGET_TYPE_HEADER_VIEW);
256 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
258 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
259 /* for MsgViewWindows, we simply return a list with one element */
261 TnyList *list = NULL;
263 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
264 if (header != NULL) {
265 list = tny_simple_list_new ();
266 tny_list_prepend (list, G_OBJECT(header));
267 g_object_unref (G_OBJECT(header));
277 headers_action_mark_as_read (TnyHeader *header,
281 TnyHeaderFlags flags;
283 g_return_if_fail (TNY_IS_HEADER(header));
285 flags = tny_header_get_flags (header);
286 if (flags & TNY_HEADER_FLAG_SEEN) return;
287 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
291 headers_action_mark_as_unread (TnyHeader *header,
295 TnyHeaderFlags flags;
297 g_return_if_fail (TNY_IS_HEADER(header));
299 flags = tny_header_get_flags (header);
300 if (flags & TNY_HEADER_FLAG_SEEN) {
301 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
305 /** A convenience method, because deleting a message is
306 * otherwise complicated, and it's best to change it in one place
309 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
311 ModestMailOperation *mail_op = NULL;
312 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE,
313 win ? G_OBJECT(win) : NULL);
314 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
317 /* Always delete. TODO: Move to trash still not supported */
318 modest_mail_operation_remove_msg (mail_op, header, FALSE);
319 g_object_unref (G_OBJECT (mail_op));
322 /** A convenience method, because deleting a message is
323 * otherwise complicated, and it's best to change it in one place
326 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
328 ModestMailOperation *mail_op = NULL;
329 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE,
330 win ? G_OBJECT(win) : NULL);
331 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
334 /* Always delete. TODO: Move to trash still not supported */
335 modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
336 g_object_unref (G_OBJECT (mail_op));
340 /* headers_action_delete (TnyHeader *header, */
341 /* ModestWindow *win, */
342 /* gpointer user_data) */
344 /* modest_do_message_delete (header, win); */
348 /** After deleing a message that is currently visible in a window,
349 * show the next message from the list, or close the window if there are no more messages.
351 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
353 /* Close msg view window or select next */
354 if (modest_msg_view_window_last_message_selected (win) &&
355 modest_msg_view_window_first_message_selected (win)) {
356 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
358 if (!modest_msg_view_window_select_next_message (win)) {
360 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
366 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
368 TnyList *header_list = NULL;
369 TnyIterator *iter = NULL;
370 TnyHeader *header = NULL;
371 gchar *message = NULL;
374 ModestWindowMgr *mgr;
375 GtkWidget *header_view = NULL;
377 g_return_if_fail (MODEST_IS_WINDOW(win));
379 /* Check first if the header view has the focus */
380 if (MODEST_IS_MAIN_WINDOW (win)) {
382 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
383 MODEST_WIDGET_TYPE_HEADER_VIEW);
384 if (!gtk_widget_is_focus (header_view))
388 /* Get the headers, either from the header view (if win is the main window),
389 * or from the message view window: */
390 header_list = get_selected_headers (win);
391 if (!header_list) return;
393 /* Check if any of the headers are already opened, or in the process of being opened */
394 if (MODEST_IS_MAIN_WINDOW (win)) {
396 iter = tny_list_create_iterator (header_list);
398 mgr = modest_runtime_get_window_mgr ();
399 while (!tny_iterator_is_done (iter) && !found) {
400 header = TNY_HEADER (tny_iterator_get_current (iter));
402 found = modest_window_mgr_find_registered_header (mgr, header, NULL);
403 g_object_unref (header);
406 tny_iterator_next (iter);
408 g_object_unref (iter);
413 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
414 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
416 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
420 g_object_unref (header_list);
426 if (tny_list_get_length(header_list) == 1) {
427 iter = tny_list_create_iterator (header_list);
428 header = TNY_HEADER (tny_iterator_get_current (iter));
430 desc = g_strdup_printf ("%s", tny_header_get_subject (header));
431 g_object_unref (header);
434 g_object_unref (iter);
436 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
437 tny_list_get_length(header_list)), desc);
439 /* Confirmation dialog */
440 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
444 if (response == GTK_RESPONSE_OK) {
445 ModestWindow *main_window = NULL;
446 ModestWindowMgr *mgr = NULL;
447 GtkTreeModel *model = NULL;
448 GtkTreeSelection *sel = NULL;
449 GList *sel_list = NULL, *tmp = NULL;
450 GtkTreeRowReference *row_reference = NULL;
451 GtkTreePath *next_path = NULL;
454 /* Find last selected row */
455 if (MODEST_IS_MAIN_WINDOW (win)) {
456 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
457 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
458 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
459 for (tmp=sel_list; tmp; tmp=tmp->next) {
460 if (tmp->next == NULL) {
461 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
462 gtk_tree_path_next (next_path);
463 row_reference = gtk_tree_row_reference_new (model, next_path);
464 gtk_tree_path_free (next_path);
469 /* Disable window dimming management */
470 modest_window_disable_dimming (MODEST_WINDOW(win));
472 /* Remove each header. If it's a view window header_view == NULL */
473 /* do_headers_action (win, headers_action_delete, header_view); */
474 modest_do_messages_delete (header_list, win);
477 /* Enable window dimming management */
478 gtk_tree_selection_unselect_all (sel);
479 modest_window_enable_dimming (MODEST_WINDOW(win));
481 /* FIXME: May be folder_monitor will also refilter treemode on EXPUNGE changes ? */
482 /* refresh the header view (removing marked-as-deleted) */
483 /* modest_header_view_refilter (MODEST_HEADER_VIEW(header_view)); */
485 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
486 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
488 /* Get main window */
489 mgr = modest_runtime_get_window_mgr ();
490 main_window = modest_window_mgr_get_main_window (mgr);
493 /* Move cursor to next row */
496 /* Select next row */
497 if (gtk_tree_row_reference_valid (row_reference)) {
498 next_path = gtk_tree_row_reference_get_path (row_reference);
499 gtk_tree_selection_select_path (sel, next_path);
500 gtk_tree_path_free (next_path);
502 if (row_reference != NULL)
503 gtk_tree_row_reference_free (row_reference);
507 printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
511 /* Update toolbar dimming state */
512 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
515 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
516 g_list_free (sel_list);
522 g_object_unref (header_list);
528 /* delete either message or folder, based on where we are */
530 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
532 g_return_if_fail (MODEST_IS_WINDOW(win));
534 /* Check first if the header view has the focus */
535 if (MODEST_IS_MAIN_WINDOW (win)) {
537 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
538 MODEST_WIDGET_TYPE_FOLDER_VIEW);
539 if (gtk_widget_is_focus (w)) {
540 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
544 modest_ui_actions_on_delete_message (action, win);
550 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
552 #ifdef MODEST_PLATFORM_MAEMO
553 modest_osso_save_state();
554 #endif /* MODEST_PLATFORM_MAEMO */
556 g_debug ("closing down, clearing %d item(s) from operation queue",
557 modest_mail_operation_queue_num_elements
558 (modest_runtime_get_mail_operation_queue()));
560 /* cancel all outstanding operations */
561 modest_mail_operation_queue_cancel_all
562 (modest_runtime_get_mail_operation_queue());
564 g_debug ("queue has been cleared");
566 /* note: when modest-tny-account-store is finalized,
567 it will automatically set all network connections
574 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
578 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
580 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
581 /* gtk_widget_destroy (GTK_WIDGET (win)); */
582 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
583 /* gboolean ret_value; */
584 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
585 /* } else if (MODEST_IS_WINDOW (win)) { */
586 /* gtk_widget_destroy (GTK_WIDGET (win)); */
588 /* g_return_if_reached (); */
593 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
595 GtkClipboard *clipboard = NULL;
596 gchar *selection = NULL;
598 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
599 selection = gtk_clipboard_wait_for_text (clipboard);
601 /* Question: why is the clipboard being used here?
602 * It doesn't really make a lot of sense. */
606 modest_address_book_add_address (selection);
612 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
614 /* This is currently only implemented for Maemo */
615 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
616 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
617 modest_run_account_setup_wizard (win);
620 /* Show the list of accounts: */
621 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
622 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
624 /* Don't make this a modal window, because secondary windows will then
625 * be unusable, freezing the UI: */
626 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
627 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win);
630 GtkWidget *dialog, *label;
632 /* Create the widgets */
634 dialog = gtk_dialog_new_with_buttons ("Message",
636 GTK_DIALOG_DESTROY_WITH_PARENT,
640 label = gtk_label_new ("Hello World!");
642 /* Ensure that the dialog box is destroyed when the user responds. */
644 g_signal_connect_swapped (dialog, "response",
645 G_CALLBACK (gtk_widget_destroy),
648 /* Add the label, and show everything we've added to the dialog. */
650 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
652 gtk_widget_show_all (dialog);
653 #endif /* MODEST_PLATFORM_MAEMO */
657 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
659 ModestWindow *main_window = MODEST_WINDOW (user_data);
661 /* Save any changes. */
662 modest_connection_specific_smtp_window_save_server_accounts (
663 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window),
664 modest_window_get_active_account (main_window));
665 gtk_widget_destroy (GTK_WIDGET (window));
671 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
673 /* This is currently only implemented for Maemo,
674 * because it requires an API (libconic) to detect different connection
677 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
679 /* Create the window if necessary: */
680 const gchar *active_account_name = modest_window_get_active_account (win);
682 /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
683 * or show the default account?
684 * If we show the default account then the account name should be shown in
685 * the window when we show it. */
686 if (!active_account_name) {
687 g_warning ("%s: No account is active.", __FUNCTION__);
691 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
692 modest_connection_specific_smtp_window_fill_with_connections (
693 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
694 modest_runtime_get_account_mgr(),
695 active_account_name);
697 /* Show the window: */
698 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
699 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
700 gtk_widget_show (specific_window);
702 /* Save changes when the window is hidden: */
703 g_signal_connect (specific_window, "hide",
704 G_CALLBACK (on_smtp_servers_window_hide), win);
705 #endif /* MODEST_PLATFORM_MAEMO */
709 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
711 ModestWindow *msg_win = NULL;
713 TnyFolder *folder = NULL;
714 gchar *account_name = NULL;
715 gchar *from_str = NULL;
716 /* GError *err = NULL; */
717 TnyAccount *account = NULL;
718 ModestWindowMgr *mgr;
719 gchar *signature = NULL, *blank_and_signature = NULL;
721 /* if there are no accounts yet, just show the wizard */
722 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
723 const gboolean created = modest_run_account_setup_wizard (win);
728 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
730 account_name = g_strdup (modest_window_get_active_account (win));
732 g_printerr ("modest: no account found\n");
736 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
738 TNY_ACCOUNT_TYPE_STORE);
740 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
744 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
746 g_printerr ("modest: failed get from string for '%s'\n", account_name);
750 gboolean use_signature = FALSE;
751 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
754 blank_and_signature = g_strconcat ("\n", signature, NULL);
756 blank_and_signature = g_strdup ("");
761 msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
763 g_printerr ("modest: failed to create new msg\n");
767 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
769 g_printerr ("modest: failed to find Drafts folder\n");
774 /* Create and register edit window */
775 /* This is destroyed by TODO. */
776 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
777 mgr = modest_runtime_get_window_mgr ();
778 modest_window_mgr_register_window (mgr, msg_win);
781 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
783 gtk_widget_show_all (GTK_WIDGET (msg_win));
786 g_free (account_name);
788 g_free (blank_and_signature);
790 g_object_unref (msg_win);
792 g_object_unref (G_OBJECT(account));
794 g_object_unref (G_OBJECT(msg));
796 g_object_unref (G_OBJECT(folder));
800 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
804 ModestMailOperationStatus status;
806 /* If there is no message or the operation was not successful */
807 status = modest_mail_operation_get_status (mail_op);
808 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
810 /* Remove the header from the preregistered uids */
811 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
821 open_msg_cb (ModestMailOperation *mail_op,
826 ModestWindowMgr *mgr = NULL;
827 ModestWindow *parent_win = NULL;
828 ModestWindow *win = NULL;
829 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
830 gchar *account = NULL;
833 /* Do nothing if there was any problem with the mail
834 operation. The error will be shown by the error_handler of
835 the mail operation */
836 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
840 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
841 folder = tny_header_get_folder (header);
843 /* Mark header as read */
844 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
847 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
849 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
851 /* Gets folder type (OUTBOX headers will be opened in edit window */
852 if (modest_tny_folder_is_local_folder (folder))
853 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
855 /* If the header is in the drafts folder then open the editor,
856 else the message view window */
857 if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
858 (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
859 /* we cannot edit without a valid account... */
860 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
861 const gboolean created = modest_run_account_setup_wizard(parent_win);
865 win = modest_msg_edit_window_new (msg, account, TRUE);
868 gchar *uid = modest_tny_folder_get_header_unique_id (header);
870 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
871 GtkWidget *header_view;
872 GtkTreeSelection *sel;
873 GList *sel_list = NULL;
876 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
877 MODEST_WIDGET_TYPE_HEADER_VIEW);
879 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
880 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
882 if (sel_list != NULL) {
883 GtkTreeRowReference *row_reference;
885 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
886 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
887 g_list_free (sel_list);
889 win = modest_msg_view_window_new_with_header_model (
890 msg, account, (const gchar*) uid,
891 model, row_reference);
892 gtk_tree_row_reference_free (row_reference);
894 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
897 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
902 /* Register and show new window */
904 mgr = modest_runtime_get_window_mgr ();
905 modest_window_mgr_register_window (mgr, win);
906 g_object_unref (win);
907 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
908 gtk_widget_show_all (GTK_WIDGET(win));
911 /* Update toolbar dimming state */
912 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
913 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
919 g_object_unref (parent_win);
920 g_object_unref (folder);
924 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
928 GObject *win = modest_mail_operation_get_source (mail_op);
930 error = modest_mail_operation_get_error (mail_op);
931 printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
933 if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
935 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
938 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
939 _("mail_ni_ui_folder_get_msg_folder_error"));
943 g_object_unref (win);
947 * This function is used by both modest_ui_actions_on_open and
948 * modest_ui_actions_on_header_activated. This way we always do the
949 * same when trying to open messages.
952 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
954 ModestWindowMgr *mgr = NULL;
955 TnyIterator *iter = NULL;
956 ModestMailOperation *mail_op = NULL;
957 TnyList *not_opened_headers = NULL;
958 TnyHeaderFlags flags = 0;
960 g_return_if_fail (headers != NULL);
962 /* Check that only one message is selected for opening */
963 if (tny_list_get_length (headers) != 1) {
964 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
965 _("mcen_ib_select_one_message"));
970 /* Look if we already have a message view for each header. If
971 true, then remove the header from the list of headers to
973 mgr = modest_runtime_get_window_mgr ();
974 iter = tny_list_create_iterator (headers);
975 not_opened_headers = tny_simple_list_new ();
977 while (!tny_iterator_is_done (iter)) {
979 ModestWindow *window = NULL;
980 TnyHeader *header = NULL;
981 gboolean found = FALSE;
983 header = TNY_HEADER (tny_iterator_get_current (iter));
985 flags = tny_header_get_flags (header);
988 found = modest_window_mgr_find_registered_header (mgr, header, &window);
990 /* Do not open again the message and present the
991 window to the user */
994 gtk_window_present (GTK_WINDOW (window));
996 /* the header has been registered already, we don't do
997 * anything but wait for the window to come up*/
998 g_debug ("header %p already registered, waiting for window", header);
1000 tny_list_append (not_opened_headers, G_OBJECT (header));
1004 g_object_unref (header);
1006 tny_iterator_next (iter);
1008 g_object_unref (iter);
1011 /* If some messages would have to be downloaded, ask the user to
1012 * make a connection. It's generally easier to do this here (in the mainloop)
1013 * than later in a thread:
1015 if (tny_list_get_length (not_opened_headers) > 0) {
1017 gboolean found = FALSE;
1019 iter = tny_list_create_iterator (not_opened_headers);
1020 while (!tny_iterator_is_done (iter) && !found) {
1021 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1022 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1025 tny_iterator_next (iter);
1027 g_object_unref (header);
1029 g_object_unref (iter);
1031 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1032 g_object_unref (not_opened_headers);
1037 /* Register the headers before actually creating the windows: */
1038 TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1039 while (!tny_iterator_is_done (iter_not_opened)) {
1040 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1042 modest_window_mgr_register_header (mgr, header);
1043 g_object_unref (header);
1046 tny_iterator_next (iter_not_opened);
1048 g_object_unref (iter_not_opened);
1049 iter_not_opened = NULL;
1051 /* Open each message */
1052 if (tny_list_get_length (not_opened_headers) > 0) {
1053 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1055 modest_ui_actions_get_msgs_full_error_handler,
1057 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1058 if (tny_list_get_length (not_opened_headers) > 1) {
1059 modest_mail_operation_get_msgs_full (mail_op,
1065 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1066 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1067 modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1068 g_object_unref (header);
1069 g_object_unref (iter);
1071 g_object_unref (mail_op);
1075 if (not_opened_headers != NULL)
1076 g_object_unref (not_opened_headers);
1080 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1085 headers = get_selected_headers (win);
1090 _modest_ui_actions_open (headers, win);
1092 g_object_unref(headers);
1097 free_reply_forward_helper (gpointer data)
1099 ReplyForwardHelper *helper;
1101 helper = (ReplyForwardHelper *) data;
1102 g_free (helper->account_name);
1103 g_slice_free (ReplyForwardHelper, helper);
1107 reply_forward_cb (ModestMailOperation *mail_op,
1113 ReplyForwardHelper *rf_helper;
1114 ModestWindow *msg_win = NULL;
1115 ModestEditType edit_type;
1117 TnyAccount *account = NULL;
1118 ModestWindowMgr *mgr = NULL;
1119 gchar *signature = NULL;
1121 /* If there was any error. The mail operation could be NULL,
1122 this means that we already have the message downloaded and
1123 that we didn't do a mail operation to retrieve it */
1124 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1127 g_return_if_fail (user_data != NULL);
1128 rf_helper = (ReplyForwardHelper *) user_data;
1130 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1131 rf_helper->account_name);
1132 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1133 rf_helper->account_name,
1134 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1135 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1136 rf_helper->account_name,
1137 MODEST_ACCOUNT_SIGNATURE, FALSE);
1140 /* Create reply mail */
1141 switch (rf_helper->action) {
1144 modest_tny_msg_create_reply_msg (msg, header, from, signature,
1145 rf_helper->reply_forward_type,
1146 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1148 case ACTION_REPLY_TO_ALL:
1150 modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1151 MODEST_TNY_MSG_REPLY_MODE_ALL);
1152 edit_type = MODEST_EDIT_TYPE_REPLY;
1154 case ACTION_FORWARD:
1156 modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1157 edit_type = MODEST_EDIT_TYPE_FORWARD;
1160 g_return_if_reached ();
1167 g_printerr ("modest: failed to create message\n");
1171 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1172 rf_helper->account_name,
1173 TNY_ACCOUNT_TYPE_STORE);
1175 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1179 /* Create and register the windows */
1180 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1181 mgr = modest_runtime_get_window_mgr ();
1182 modest_window_mgr_register_window (mgr, msg_win);
1184 if (rf_helper->parent_window != NULL) {
1185 gdouble parent_zoom;
1187 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1188 modest_window_set_zoom (msg_win, parent_zoom);
1191 /* Show edit window */
1192 gtk_widget_show_all (GTK_WIDGET (msg_win));
1196 g_object_unref (msg_win);
1198 g_object_unref (G_OBJECT (new_msg));
1200 g_object_unref (G_OBJECT (account));
1201 /* g_object_unref (msg); */
1202 free_reply_forward_helper (rf_helper);
1205 /* Checks a list of headers. If any of them are not currently
1206 * downloaded (CACHED) then returns TRUE else returns FALSE.
1209 header_list_count_uncached_msgs (
1210 TnyList *header_list,
1214 gint uncached_messages = 0;
1216 iter = tny_list_create_iterator (header_list);
1217 while (!tny_iterator_is_done (iter)) {
1220 header = TNY_HEADER (tny_iterator_get_current (iter));
1222 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1223 uncached_messages ++;
1224 g_object_unref (header);
1227 tny_iterator_next (iter);
1229 g_object_unref (iter);
1231 return uncached_messages;
1234 /* Returns FALSE if the user does not want to download the
1235 * messages. Returns TRUE if the user allowed the download.
1238 download_uncached_messages (
1240 gint num_of_uncached_msgs)
1242 /* Allways download if we are online. */
1243 if (tny_device_is_online (modest_runtime_get_device()))
1246 /* If offline, then ask for user permission to download the messages */
1247 GtkResponseType response;
1248 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1249 ngettext("mcen_nc_get_msg",
1251 num_of_uncached_msgs));
1252 if (response == GTK_RESPONSE_CANCEL)
1255 return modest_platform_connect_and_wait(win, NULL);
1259 * Common code for the reply and forward actions
1262 reply_forward (ReplyForwardAction action, ModestWindow *win)
1264 ModestMailOperation *mail_op = NULL;
1265 TnyList *header_list = NULL;
1266 ReplyForwardHelper *rf_helper = NULL;
1267 guint reply_forward_type;
1268 gboolean continue_download = TRUE;
1269 gboolean do_retrieve = TRUE;
1271 g_return_if_fail (MODEST_IS_WINDOW(win));
1273 /* we need an account when editing */
1274 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1275 const gboolean created = modest_run_account_setup_wizard (win);
1280 header_list = get_selected_headers (win);
1284 reply_forward_type =
1285 modest_conf_get_int (modest_runtime_get_conf (),
1286 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1289 /* check if we need to download msg before asking about it */
1290 do_retrieve = (action == ACTION_FORWARD) ||
1291 (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1294 gint num_of_unc_msgs;
1295 /* check that the messages have been previously downloaded */
1296 num_of_unc_msgs = header_list_count_uncached_msgs(
1299 /* If there are any uncached message ask the user
1300 * whether he/she wants to download them. */
1301 if (num_of_unc_msgs)
1302 continue_download = download_uncached_messages (
1307 if (!continue_download) {
1308 g_object_unref (header_list);
1312 /* We assume that we can only select messages of the
1313 same folder and that we reply all of them from the
1314 same account. In fact the interface currently only
1315 allows single selection */
1318 rf_helper = g_slice_new0 (ReplyForwardHelper);
1319 rf_helper->reply_forward_type = reply_forward_type;
1320 rf_helper->action = action;
1321 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1323 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1324 rf_helper->parent_window = GTK_WIDGET (win);
1325 if (!rf_helper->account_name)
1326 rf_helper->account_name =
1327 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1329 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1332 /* Get header and message. Do not free them here, the
1333 reply_forward_cb must do it */
1334 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1335 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1336 if (!msg || !header) {
1338 g_object_unref (msg);
1339 g_printerr ("modest: no message found\n");
1342 reply_forward_cb (NULL, header, msg, rf_helper);
1345 g_object_unref (header);
1350 /* Only reply/forward to one message */
1351 iter = tny_list_create_iterator (header_list);
1352 header = TNY_HEADER (tny_iterator_get_current (iter));
1353 g_object_unref (iter);
1356 /* Retrieve messages */
1358 mail_op = modest_mail_operation_new_with_error_handling (
1359 MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1361 modest_ui_actions_get_msgs_full_error_handler,
1363 modest_mail_operation_queue_add (
1364 modest_runtime_get_mail_operation_queue (), mail_op);
1366 modest_mail_operation_get_msg (mail_op,
1371 g_object_unref(mail_op);
1373 /* we put a ref here to prevent double unref as the reply
1374 * forward callback unrefs the header at its end */
1375 reply_forward_cb (NULL, header, NULL, rf_helper);
1379 g_object_unref (header);
1385 g_object_unref (header_list);
1389 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1391 g_return_if_fail (MODEST_IS_WINDOW(win));
1393 reply_forward (ACTION_REPLY, win);
1397 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1399 g_return_if_fail (MODEST_IS_WINDOW(win));
1401 reply_forward (ACTION_FORWARD, win);
1405 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1407 g_return_if_fail (MODEST_IS_WINDOW(win));
1409 reply_forward (ACTION_REPLY_TO_ALL, win);
1413 modest_ui_actions_on_next (GtkAction *action,
1414 ModestWindow *window)
1416 if (MODEST_IS_MAIN_WINDOW (window)) {
1417 GtkWidget *header_view;
1419 header_view = modest_main_window_get_child_widget (
1420 MODEST_MAIN_WINDOW(window),
1421 MODEST_WIDGET_TYPE_HEADER_VIEW);
1425 modest_header_view_select_next (
1426 MODEST_HEADER_VIEW(header_view));
1427 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1428 modest_msg_view_window_select_next_message (
1429 MODEST_MSG_VIEW_WINDOW (window));
1431 g_return_if_reached ();
1436 modest_ui_actions_on_prev (GtkAction *action,
1437 ModestWindow *window)
1439 g_return_if_fail (MODEST_IS_WINDOW(window));
1441 if (MODEST_IS_MAIN_WINDOW (window)) {
1442 GtkWidget *header_view;
1443 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1444 MODEST_WIDGET_TYPE_HEADER_VIEW);
1448 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1449 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1450 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1452 g_return_if_reached ();
1457 modest_ui_actions_on_sort (GtkAction *action,
1458 ModestWindow *window)
1460 g_return_if_fail (MODEST_IS_WINDOW(window));
1462 if (MODEST_IS_MAIN_WINDOW (window)) {
1463 GtkWidget *header_view;
1464 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1465 MODEST_WIDGET_TYPE_HEADER_VIEW);
1467 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1472 /* Show sorting dialog */
1473 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1478 new_messages_arrived (ModestMailOperation *self,
1482 ModestMainWindow *win = NULL;
1483 GtkWidget *folder_view = NULL;
1484 TnyFolderStore *folder = NULL;
1485 gboolean folder_empty = FALSE;
1487 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1488 win = MODEST_MAIN_WINDOW (user_data);
1490 /* Set contents style of headers view */
1491 if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1492 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1493 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1494 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1497 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1500 modest_main_window_set_contents_style (win,
1501 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1504 /* Notify new messages have been downloaded */
1505 if (new_messages > 0)
1506 modest_platform_on_new_msg ();
1510 * This function performs the send & receive required actions. The
1511 * window is used to create the mail operation. Typically it should
1512 * always be the main window, but we pass it as argument in order to
1516 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1518 gchar *acc_name = NULL;
1519 ModestMailOperation *mail_op;
1521 /* If no account name was provided then get the current account, and if
1522 there is no current account then pick the default one: */
1523 if (!account_name) {
1524 acc_name = g_strdup (modest_window_get_active_account(win));
1526 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1528 g_printerr ("modest: cannot get default account\n");
1532 acc_name = g_strdup (account_name);
1535 /* Set send/receive operation in progress */
1536 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1538 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1540 modest_ui_actions_send_receive_error_handler,
1543 g_signal_connect (G_OBJECT(mail_op), "progress-changed",
1544 G_CALLBACK (_on_send_receive_progress_changed),
1547 /* Send & receive. */
1548 /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1549 /* Receive and then send. The operation is tagged initially as
1550 a receive operation because the account update performs a
1551 receive and then a send. The operation changes its type
1552 internally, so the progress objects will receive the proper
1553 progress information */
1554 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1555 modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1556 g_object_unref (G_OBJECT (mail_op));
1564 modest_ui_actions_do_cancel_send (const gchar *account_name,
1567 TnyTransportAccount *transport_account;
1568 TnySendQueue *send_queue = NULL;
1569 GError *error = NULL;
1571 /* Get transport account */
1573 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1574 (modest_runtime_get_account_store(),
1576 TNY_ACCOUNT_TYPE_TRANSPORT));
1577 if (!transport_account) {
1578 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1583 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1584 if (!TNY_IS_SEND_QUEUE(send_queue)) {
1585 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1586 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1587 "modest: could not find send queue for account\n");
1589 /* Keeep messages in outbox folder */
1590 tny_send_queue_cancel (send_queue, FALSE, &error);
1594 if (transport_account != NULL)
1595 g_object_unref (G_OBJECT (transport_account));
1599 modest_ui_actions_cancel_send_all (ModestWindow *win)
1601 GSList *account_names, *iter;
1603 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1606 iter = account_names;
1608 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1609 iter = g_slist_next (iter);
1612 modest_account_mgr_free_account_names (account_names);
1613 account_names = NULL;
1617 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
1620 /* Check if accounts exist */
1621 gboolean accounts_exist =
1622 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1624 /* If not, allow the user to create an account before trying to send/receive. */
1625 if (!accounts_exist)
1626 modest_ui_actions_on_accounts (NULL, win);
1628 /* Cancel all sending operaitons */
1629 modest_ui_actions_cancel_send_all (win);
1633 * Refreshes all accounts. This function will be used by automatic
1637 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1639 GSList *account_names, *iter;
1641 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1644 iter = account_names;
1646 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1647 iter = g_slist_next (iter);
1650 modest_account_mgr_free_account_names (account_names);
1651 account_names = NULL;
1655 modest_do_refresh_current_folder(ModestWindow *win)
1657 /* Refresh currently selected folder. Note that if we only
1658 want to retreive the headers, then the refresh only will
1659 invoke a poke_status over all folders, i.e., only the
1660 total/unread count will be updated */
1661 if (MODEST_IS_MAIN_WINDOW (win)) {
1662 GtkWidget *header_view, *folder_view;
1663 TnyFolderStore *folder_store;
1665 /* Get folder and header view */
1667 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1668 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1672 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1674 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1676 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1677 MODEST_WIDGET_TYPE_HEADER_VIEW);
1679 /* We do not need to set the contents style
1680 because it hasn't changed. We also do not
1681 need to save the widget status. Just force
1683 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1684 TNY_FOLDER (folder_store),
1685 folder_refreshed_cb,
1686 MODEST_MAIN_WINDOW (win));
1690 g_object_unref (folder_store);
1696 * Handler of the click on Send&Receive button in the main toolbar
1699 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1701 /* Check if accounts exist */
1702 gboolean accounts_exist =
1703 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1705 /* If not, allow the user to create an account before trying to send/receive. */
1706 if (!accounts_exist)
1707 modest_ui_actions_on_accounts (NULL, win);
1709 modest_do_refresh_current_folder (win);
1711 /* Refresh the active account */
1712 modest_ui_actions_do_send_receive (NULL, win);
1717 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1720 GtkWidget *header_view;
1722 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1724 header_view = modest_main_window_get_child_widget (main_window,
1725 MODEST_WIDGET_TYPE_HEADER_VIEW);
1729 conf = modest_runtime_get_conf ();
1731 /* what is saved/restored is depending on the style; thus; we save with
1732 * old style, then update the style, and restore for this new style
1734 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1736 if (modest_header_view_get_style
1737 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1738 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1739 MODEST_HEADER_VIEW_STYLE_TWOLINES);
1741 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1742 MODEST_HEADER_VIEW_STYLE_DETAILS);
1744 modest_widget_memory_restore (conf, G_OBJECT(header_view),
1745 MODEST_CONF_HEADER_VIEW_KEY);
1750 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
1752 ModestMainWindow *main_window)
1754 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1755 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1757 /* in the case the folder is empty, show the empty folder message and focus
1759 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1760 if (modest_header_view_is_empty (header_view)) {
1761 TnyFolder *folder = modest_header_view_get_folder (header_view);
1762 GtkWidget *folder_view =
1763 modest_main_window_get_child_widget (main_window,
1764 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1766 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1767 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1771 /* If no header has been selected then exit */
1776 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1777 gtk_widget_grab_focus (GTK_WIDGET(header_view));
1779 /* Update toolbar dimming state */
1780 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1784 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1786 ModestMainWindow *main_window)
1790 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1796 /* headers = tny_simple_list_new (); */
1797 /* tny_list_prepend (headers, G_OBJECT (header)); */
1798 headers = modest_header_view_get_selected_headers (header_view);
1800 _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1802 g_object_unref (headers);
1806 set_active_account_from_tny_account (TnyAccount *account,
1807 ModestWindow *window)
1809 const gchar *server_acc_name = tny_account_get_id (account);
1811 /* We need the TnyAccount provided by the
1812 account store because that is the one that
1813 knows the name of the Modest account */
1814 TnyAccount *modest_server_account = modest_server_account =
1815 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1816 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
1819 const gchar *modest_acc_name =
1820 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1821 modest_window_set_active_account (window, modest_acc_name);
1822 g_object_unref (modest_server_account);
1827 folder_refreshed_cb (ModestMailOperation *mail_op,
1831 ModestMainWindow *win = NULL;
1832 GtkWidget *header_view;
1833 TnyFolder *current_folder;
1834 gboolean folder_empty = FALSE;
1835 gboolean all_marked_as_deleted = FALSE;
1837 g_return_if_fail (TNY_IS_FOLDER (folder));
1839 win = MODEST_MAIN_WINDOW (user_data);
1841 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1844 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1845 if (current_folder != NULL && folder != current_folder) {
1850 /* Check if folder is empty and set headers view contents style */
1851 folder_empty = (tny_folder_get_all_count (folder) == 0);
1852 all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1853 folder_empty = folder_empty || all_marked_as_deleted ;
1856 printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1857 modest_main_window_set_contents_style (win,
1858 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1860 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1865 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1866 TnyFolderStore *folder_store,
1868 ModestMainWindow *main_window)
1871 GtkWidget *header_view;
1873 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1875 header_view = modest_main_window_get_child_widget(main_window,
1876 MODEST_WIDGET_TYPE_HEADER_VIEW);
1880 conf = modest_runtime_get_conf ();
1882 if (TNY_IS_ACCOUNT (folder_store)) {
1884 /* Update active account */
1885 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1886 /* Show account details */
1887 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1890 if (TNY_IS_FOLDER (folder_store) && selected) {
1892 /* Update the active account */
1893 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1895 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1896 g_object_unref (account);
1900 /* Set the header style by default, it could
1901 be changed later by the refresh callback to
1903 modest_main_window_set_contents_style (main_window,
1904 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1906 /* Set folder on header view. This function
1907 will call tny_folder_refresh_async so we
1908 pass a callback that will be called when
1909 finished. We use that callback to set the
1910 empty view if there are no messages */
1911 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1912 TNY_FOLDER (folder_store),
1913 folder_refreshed_cb,
1916 /* Restore configuration. We need to do this
1917 *after* the set_folder because the widget
1918 memory asks the header view about its
1920 modest_widget_memory_restore (modest_runtime_get_conf (),
1921 G_OBJECT(header_view),
1922 MODEST_CONF_HEADER_VIEW_KEY);
1924 /* Update the active account */
1925 modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1926 /* Save only if we're seeing headers */
1927 if (modest_main_window_get_contents_style (main_window) ==
1928 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1929 modest_widget_memory_save (conf, G_OBJECT (header_view),
1930 MODEST_CONF_HEADER_VIEW_KEY);
1931 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1935 /* Update toolbar dimming state */
1936 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1940 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1947 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1949 online = tny_device_is_online (modest_runtime_get_device());
1952 /* already online -- the item is simply not there... */
1953 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1955 GTK_MESSAGE_WARNING,
1957 _("The %s you selected cannot be found"),
1959 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
1960 gtk_dialog_run (GTK_DIALOG(dialog));
1962 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1965 _("mcen_bd_dialog_cancel"),
1966 GTK_RESPONSE_REJECT,
1967 _("mcen_bd_dialog_ok"),
1968 GTK_RESPONSE_ACCEPT,
1970 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1971 "Do you want to get online?"), item);
1972 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1973 gtk_label_new (txt), FALSE, FALSE, 0);
1974 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1977 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1978 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1979 /* TODO: Comment about why is this commented out: */
1980 /* modest_platform_connect_and_wait (); */
1983 gtk_widget_destroy (dialog);
1987 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1990 /* g_message ("%s %s", __FUNCTION__, link); */
1995 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1998 modest_platform_activate_uri (link);
2002 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2005 modest_platform_show_uri_popup (link);
2009 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2012 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2016 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2017 const gchar *address,
2020 /* g_message ("%s %s", __FUNCTION__, address); */
2024 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2026 TnyTransportAccount *transport_account;
2027 ModestMailOperation *mail_operation;
2029 gchar *account_name, *from;
2030 ModestAccountMgr *account_mgr;
2031 gchar *info_text = NULL;
2033 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2035 data = modest_msg_edit_window_get_msg_data (edit_window);
2037 account_mgr = modest_runtime_get_account_mgr();
2038 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2040 account_name = modest_account_mgr_get_default_account (account_mgr);
2041 if (!account_name) {
2042 g_printerr ("modest: no account found\n");
2043 modest_msg_edit_window_free_msg_data (edit_window, data);
2047 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2048 account_name = g_strdup (data->account_name);
2052 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2053 (modest_runtime_get_account_store(),
2055 TNY_ACCOUNT_TYPE_TRANSPORT));
2056 if (!transport_account) {
2057 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2058 g_free (account_name);
2059 modest_msg_edit_window_free_msg_data (edit_window, data);
2062 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2064 /* Create the mail operation */
2065 mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2066 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2068 modest_mail_operation_save_to_drafts (mail_operation,
2080 data->priority_flags);
2083 g_free (account_name);
2084 g_object_unref (G_OBJECT (transport_account));
2085 g_object_unref (G_OBJECT (mail_operation));
2087 modest_msg_edit_window_free_msg_data (edit_window, data);
2089 info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2090 modest_platform_information_banner (NULL, NULL, info_text);
2094 /* For instance, when clicking the Send toolbar button when editing a message: */
2096 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2098 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2100 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2103 /* Offer the connection dialog, if necessary: */
2104 if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2107 /* FIXME: Code added just for testing. The final version will
2108 use the send queue provided by tinymail and some
2110 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2111 gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2113 account_name = modest_account_mgr_get_default_account (account_mgr);
2115 if (!account_name) {
2116 /* Run account setup wizard */
2117 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2122 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2124 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2125 account_name = g_strdup (data->account_name);
2128 /* Get the currently-active transport account for this modest account: */
2129 TnyTransportAccount *transport_account =
2130 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2131 (modest_runtime_get_account_store(),
2133 if (!transport_account) {
2134 /* Run account setup wizard */
2135 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2140 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2142 /* Create the mail operation */
2143 ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2144 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2146 modest_mail_operation_send_new_mail (mail_operation,
2157 data->priority_flags);
2161 g_free (account_name);
2162 g_object_unref (G_OBJECT (transport_account));
2163 g_object_unref (G_OBJECT (mail_operation));
2165 modest_msg_edit_window_free_msg_data (edit_window, data);
2166 modest_msg_edit_window_set_sent (edit_window, TRUE);
2168 /* Save settings and close the window: */
2169 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2173 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2174 ModestMsgEditWindow *window)
2176 ModestMsgEditFormatState *format_state = NULL;
2178 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2179 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2181 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2184 format_state = modest_msg_edit_window_get_format_state (window);
2185 g_return_if_fail (format_state != NULL);
2187 format_state->bold = gtk_toggle_action_get_active (action);
2188 modest_msg_edit_window_set_format_state (window, format_state);
2189 g_free (format_state);
2194 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2195 ModestMsgEditWindow *window)
2197 ModestMsgEditFormatState *format_state = NULL;
2199 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2200 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2202 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2205 format_state = modest_msg_edit_window_get_format_state (window);
2206 g_return_if_fail (format_state != NULL);
2208 format_state->italics = gtk_toggle_action_get_active (action);
2209 modest_msg_edit_window_set_format_state (window, format_state);
2210 g_free (format_state);
2215 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2216 ModestMsgEditWindow *window)
2218 ModestMsgEditFormatState *format_state = NULL;
2220 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2221 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2223 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2226 format_state = modest_msg_edit_window_get_format_state (window);
2227 g_return_if_fail (format_state != NULL);
2229 format_state->bullet = gtk_toggle_action_get_active (action);
2230 modest_msg_edit_window_set_format_state (window, format_state);
2231 g_free (format_state);
2236 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2237 GtkRadioAction *selected,
2238 ModestMsgEditWindow *window)
2240 ModestMsgEditFormatState *format_state = NULL;
2241 GtkJustification value;
2243 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2245 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2248 value = gtk_radio_action_get_current_value (selected);
2250 format_state = modest_msg_edit_window_get_format_state (window);
2251 g_return_if_fail (format_state != NULL);
2253 format_state->justification = value;
2254 modest_msg_edit_window_set_format_state (window, format_state);
2255 g_free (format_state);
2259 modest_ui_actions_on_select_editor_color (GtkAction *action,
2260 ModestMsgEditWindow *window)
2262 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2263 g_return_if_fail (GTK_IS_ACTION (action));
2265 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2268 modest_msg_edit_window_select_color (window);
2272 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2273 ModestMsgEditWindow *window)
2275 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2276 g_return_if_fail (GTK_IS_ACTION (action));
2278 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2281 modest_msg_edit_window_select_background_color (window);
2285 modest_ui_actions_on_insert_image (GtkAction *action,
2286 ModestMsgEditWindow *window)
2288 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2289 g_return_if_fail (GTK_IS_ACTION (action));
2291 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2294 modest_msg_edit_window_insert_image (window);
2298 modest_ui_actions_on_attach_file (GtkAction *action,
2299 ModestMsgEditWindow *window)
2301 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2302 g_return_if_fail (GTK_IS_ACTION (action));
2304 modest_msg_edit_window_offer_attach_file (window);
2308 modest_ui_actions_on_remove_attachments (GtkAction *action,
2309 ModestMsgEditWindow *window)
2311 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2312 g_return_if_fail (GTK_IS_ACTION (action));
2314 modest_msg_edit_window_remove_attachments (window, NULL);
2318 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2321 ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2322 const GError *error = modest_mail_operation_get_error (mail_op);
2326 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2327 modest_mail_operation_get_error (mail_op)->message);
2332 modest_ui_actions_create_folder(GtkWidget *parent_window,
2333 GtkWidget *folder_view)
2335 TnyFolderStore *parent_folder;
2337 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2339 if (parent_folder) {
2340 gboolean finished = FALSE;
2342 gchar *folder_name = NULL, *suggested_name = NULL;
2343 const gchar *proto_str = NULL;
2344 TnyAccount *account;
2346 if (TNY_IS_ACCOUNT (parent_folder))
2347 account = g_object_ref (parent_folder);
2349 account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2350 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2352 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2353 MODEST_PROTOCOL_STORE_POP) {
2355 hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2357 g_object_unref (account);
2359 /* Run the new folder dialog */
2361 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2366 g_free (suggested_name);
2367 suggested_name = NULL;
2369 if (result == GTK_RESPONSE_REJECT) {
2372 ModestMailOperation *mail_op;
2373 TnyFolder *new_folder = NULL;
2375 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2376 G_OBJECT(parent_window),
2377 modest_ui_actions_new_folder_error_handler,
2380 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2382 new_folder = modest_mail_operation_create_folder (mail_op,
2384 (const gchar *) folder_name);
2386 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2389 g_object_unref (new_folder);
2392 g_object_unref (mail_op);
2395 suggested_name = folder_name;
2399 g_object_unref (parent_folder);
2404 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2406 GtkWidget *folder_view;
2408 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2410 folder_view = modest_main_window_get_child_widget (main_window,
2411 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2415 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2419 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2422 ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2423 const GError *error = NULL;
2424 const gchar *message = NULL;
2426 /* Get error message */
2427 error = modest_mail_operation_get_error (mail_op);
2429 g_return_if_reached ();
2431 switch (error->code) {
2432 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2433 message = _CS("ckdg_ib_folder_already_exists");
2436 g_return_if_reached ();
2439 modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2443 modest_ui_actions_on_rename_folder (GtkAction *action,
2444 ModestMainWindow *main_window)
2446 TnyFolderStore *folder;
2447 GtkWidget *folder_view;
2448 GtkWidget *header_view;
2450 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2452 folder_view = modest_main_window_get_child_widget (main_window,
2453 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2457 header_view = modest_main_window_get_child_widget (main_window,
2458 MODEST_WIDGET_TYPE_HEADER_VIEW);
2463 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2467 /* Offer the connection dialog if necessary: */
2468 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2469 g_object_unref (G_OBJECT (folder));
2474 if (TNY_IS_FOLDER (folder)) {
2477 const gchar *current_name;
2478 TnyFolderStore *parent;
2480 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2481 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2482 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
2483 parent, current_name,
2485 g_object_unref (parent);
2487 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2488 ModestMailOperation *mail_op;
2489 GtkTreeSelection *sel = NULL;
2492 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2493 G_OBJECT(main_window),
2494 modest_ui_actions_rename_folder_error_handler,
2498 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2501 /* Clear the headers view */
2502 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2503 gtk_tree_selection_unselect_all (sel);
2505 /* Select *after* the changes */
2506 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2507 TNY_FOLDER(folder), TRUE);
2509 modest_mail_operation_rename_folder (mail_op,
2510 TNY_FOLDER (folder),
2511 (const gchar *) folder_name);
2513 g_object_unref (mail_op);
2514 g_free (folder_name);
2517 g_object_unref (folder);
2521 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2524 GObject *win = modest_mail_operation_get_source (mail_op);
2526 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2527 _("mail_in_ui_folder_delete_error"));
2528 g_object_unref (win);
2532 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2534 TnyFolderStore *folder;
2535 GtkWidget *folder_view;
2539 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2541 folder_view = modest_main_window_get_child_widget (main_window,
2542 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2546 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2548 /* Show an error if it's an account */
2549 if (!TNY_IS_FOLDER (folder)) {
2550 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2551 _("mail_in_ui_folder_delete_error"));
2552 g_object_unref (G_OBJECT (folder));
2556 /* Offer the connection dialog if necessary: */
2557 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2558 g_object_unref (G_OBJECT (folder));
2563 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
2564 tny_folder_get_name (TNY_FOLDER (folder)));
2565 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2566 (const gchar *) message);
2569 if (response == GTK_RESPONSE_OK) {
2570 ModestMailOperation *mail_op;
2571 GtkTreeSelection *sel;
2573 /* Unselect the folder before deleting it to free the headers */
2574 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2575 gtk_tree_selection_unselect_all (sel);
2577 /* Create the mail operation */
2579 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE,
2580 G_OBJECT(main_window),
2581 modest_ui_actions_delete_folder_error_handler,
2584 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2586 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2587 g_object_unref (G_OBJECT (mail_op));
2590 g_object_unref (G_OBJECT (folder));
2594 modest_ui_actions_on_delete_folder (GtkAction *action,
2595 ModestMainWindow *main_window)
2597 GtkWidget *folder_view;
2598 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2600 delete_folder (main_window, FALSE);
2601 folder_view = modest_main_window_get_child_widget (main_window,
2602 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2605 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2609 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2611 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2613 delete_folder (main_window, TRUE);
2618 show_error (GtkWidget *parent_widget, const gchar* text)
2620 hildon_banner_show_information(parent_widget, NULL, text);
2623 GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2625 GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2632 gtk_dialog_run (dialog);
2633 gtk_widget_destroy (GTK_WIDGET (dialog));
2638 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
2639 const gchar* server_account_name,
2644 ModestMainWindow *main_window)
2646 g_return_if_fail(server_account_name);
2647 /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2649 /* Initalize output parameters: */
2656 #ifdef MODEST_PLATFORM_MAEMO
2657 /* Maemo uses a different (awkward) button order,
2658 * It should probably just use gtk_alternative_dialog_button_order ().
2660 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2663 _("mcen_bd_dialog_ok"),
2664 GTK_RESPONSE_ACCEPT,
2665 _("mcen_bd_dialog_cancel"),
2666 GTK_RESPONSE_REJECT,
2669 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2673 GTK_RESPONSE_REJECT,
2675 GTK_RESPONSE_ACCEPT,
2677 #endif /* MODEST_PLATFORM_MAEMO */
2679 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2681 gchar *server_name = modest_server_account_get_hostname (
2682 modest_runtime_get_account_mgr(), server_account_name);
2683 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2684 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2689 /* This causes a warning because the logical ID has no %s in it,
2690 * though the translation does, but there is not much we can do about that: */
2691 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2692 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2695 g_free (server_name);
2699 gchar *initial_username = modest_server_account_get_username (
2700 modest_runtime_get_account_mgr(), server_account_name);
2702 GtkWidget *entry_username = gtk_entry_new ();
2703 if (initial_username)
2704 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2705 /* Dim this if a connection has ever succeeded with this username,
2706 * as per the UI spec: */
2707 const gboolean username_known =
2708 modest_server_account_get_username_has_succeeded(
2709 modest_runtime_get_account_mgr(), server_account_name);
2710 gtk_widget_set_sensitive (entry_username, !username_known);
2712 #ifdef MODEST_PLATFORM_MAEMO
2713 /* Auto-capitalization is the default, so let's turn it off: */
2714 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2716 /* Create a size group to be used by all captions.
2717 * Note that HildonCaption does not create a default size group if we do not specify one.
2718 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2719 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2721 GtkWidget *caption = hildon_caption_new (sizegroup,
2722 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2723 gtk_widget_show (entry_username);
2724 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
2725 FALSE, FALSE, MODEST_MARGIN_HALF);
2726 gtk_widget_show (caption);
2728 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2730 #endif /* MODEST_PLATFORM_MAEMO */
2733 GtkWidget *entry_password = gtk_entry_new ();
2734 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2735 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2737 #ifdef MODEST_PLATFORM_MAEMO
2738 /* Auto-capitalization is the default, so let's turn it off: */
2739 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
2740 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2742 caption = hildon_caption_new (sizegroup,
2743 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2744 gtk_widget_show (entry_password);
2745 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
2746 FALSE, FALSE, MODEST_MARGIN_HALF);
2747 gtk_widget_show (caption);
2748 g_object_unref (sizegroup);
2750 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2752 #endif /* MODEST_PLATFORM_MAEMO */
2754 /* This is not in the Maemo UI spec:
2755 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2756 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2760 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2762 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2764 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2766 modest_server_account_set_username (
2767 modest_runtime_get_account_mgr(), server_account_name,
2770 const gboolean username_was_changed =
2771 (strcmp (*username, initial_username) != 0);
2772 if (username_was_changed) {
2773 g_warning ("%s: tinymail does not yet support changing the "
2774 "username in the get_password() callback.\n", __FUNCTION__);
2779 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2781 /* We do not save the password in the configuration,
2782 * because this function is only called for passwords that should
2783 * not be remembered:
2784 modest_server_account_set_password (
2785 modest_runtime_get_account_mgr(), server_account_name,
2794 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2806 /* This is not in the Maemo UI spec:
2807 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2813 gtk_widget_destroy (dialog);
2815 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2819 modest_ui_actions_on_cut (GtkAction *action,
2820 ModestWindow *window)
2822 GtkWidget *focused_widget;
2823 GtkClipboard *clipboard;
2825 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2826 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2827 if (GTK_IS_EDITABLE (focused_widget)) {
2828 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2829 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2830 gtk_clipboard_store (clipboard);
2831 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2832 GtkTextBuffer *buffer;
2834 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2835 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2836 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2837 gtk_clipboard_store (clipboard);
2838 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2839 TnyList *header_list = modest_header_view_get_selected_headers (
2840 MODEST_HEADER_VIEW (focused_widget));
2841 gboolean continue_download = FALSE;
2842 gint num_of_unc_msgs;
2844 num_of_unc_msgs = header_list_count_uncached_msgs(
2845 header_list, GTK_WINDOW (window));
2847 if (num_of_unc_msgs)
2848 continue_download = download_uncached_messages(
2849 GTK_WINDOW (window),
2852 if (num_of_unc_msgs == 0 || continue_download) {
2853 /* modest_platform_information_banner (
2854 NULL, NULL, _CS("mcen_ib_getting_items"));*/
2855 modest_header_view_cut_selection (
2856 MODEST_HEADER_VIEW (focused_widget));
2859 g_object_unref (header_list);
2860 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2861 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2866 modest_ui_actions_on_copy (GtkAction *action,
2867 ModestWindow *window)
2869 GtkClipboard *clipboard;
2870 GtkWidget *focused_widget;
2871 gboolean copied = TRUE;
2873 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2874 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2876 if (GTK_IS_LABEL (focused_widget)) {
2877 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2878 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2879 gtk_clipboard_store (clipboard);
2880 } else if (GTK_IS_EDITABLE (focused_widget)) {
2881 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2882 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2883 gtk_clipboard_store (clipboard);
2884 } else if (GTK_IS_HTML (focused_widget)) {
2885 gtk_html_copy (GTK_HTML (focused_widget));
2886 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2887 gtk_clipboard_store (clipboard);
2888 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2889 GtkTextBuffer *buffer;
2890 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2891 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2892 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2893 gtk_clipboard_store (clipboard);
2894 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2895 TnyList *header_list = modest_header_view_get_selected_headers (
2896 MODEST_HEADER_VIEW (focused_widget));
2897 gboolean continue_download = FALSE;
2898 gint num_of_unc_msgs;
2900 num_of_unc_msgs = header_list_count_uncached_msgs(
2902 GTK_WINDOW (window));
2904 if (num_of_unc_msgs)
2905 continue_download = download_uncached_messages(
2906 GTK_WINDOW (window),
2909 if (num_of_unc_msgs == 0 || continue_download) {
2910 modest_platform_information_banner (
2911 NULL, NULL, _CS("mcen_ib_getting_items"));
2912 modest_header_view_copy_selection (
2913 MODEST_HEADER_VIEW (focused_widget));
2917 g_object_unref (header_list);
2919 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2920 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2923 /* Show information banner if there was a copy to clipboard */
2925 modest_platform_information_banner (
2926 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2930 modest_ui_actions_on_undo (GtkAction *action,
2931 ModestWindow *window)
2933 ModestEmailClipboard *clipboard = NULL;
2935 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2936 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2937 } else if (MODEST_IS_MAIN_WINDOW (window)) {
2938 /* Clear clipboard source */
2939 clipboard = modest_runtime_get_email_clipboard ();
2940 modest_email_clipboard_clear (clipboard);
2943 g_return_if_reached ();
2948 modest_ui_actions_on_redo (GtkAction *action,
2949 ModestWindow *window)
2951 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2952 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2955 g_return_if_reached ();
2961 paste_msgs_cb (const GObject *object, gpointer user_data)
2963 g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2964 g_return_if_fail (GTK_IS_WIDGET (user_data));
2966 /* destroy information note */
2967 gtk_widget_destroy (GTK_WIDGET(user_data));
2971 paste_as_attachment_free (gpointer data)
2973 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2975 gtk_widget_destroy (helper->banner);
2976 g_object_unref (helper->banner);
2981 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2986 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2987 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2992 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2997 modest_ui_actions_on_paste (GtkAction *action,
2998 ModestWindow *window)
3000 GtkWidget *focused_widget = NULL;
3001 GtkWidget *inf_note = NULL;
3002 ModestMailOperation *mail_op = NULL;
3004 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3005 if (GTK_IS_EDITABLE (focused_widget)) {
3006 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3007 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3008 ModestEmailClipboard *e_clipboard = NULL;
3009 e_clipboard = modest_runtime_get_email_clipboard ();
3010 if (modest_email_clipboard_cleared (e_clipboard)) {
3011 GtkTextBuffer *buffer;
3012 GtkClipboard *clipboard;
3014 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3015 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3016 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3017 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3018 ModestMailOperation *mail_op;
3019 TnyFolder *src_folder;
3022 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3023 helper->window = MODEST_MSG_EDIT_WINDOW (window);
3024 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3025 _CS("ckct_nw_pasting"));
3026 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3027 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3029 if (helper->banner != NULL) {
3030 g_object_ref (G_OBJECT (helper->banner));
3031 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3032 gtk_widget_show (GTK_WIDGET (helper->banner));
3036 modest_mail_operation_get_msgs_full (mail_op,
3038 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3040 paste_as_attachment_free);
3043 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3044 ModestEmailClipboard *clipboard = NULL;
3045 TnyFolder *src_folder = NULL;
3046 TnyFolderStore *folder_store = NULL;
3047 TnyList *data = NULL;
3048 gboolean delete = FALSE;
3050 /* Check clipboard source */
3051 clipboard = modest_runtime_get_email_clipboard ();
3052 if (modest_email_clipboard_cleared (clipboard))
3055 /* Get elements to paste */
3056 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3058 /* Create a new mail operation */
3059 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3061 /* Get destination folder */
3062 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3064 /* transfer messages */
3068 /* Ask for user confirmation */
3069 response = msgs_move_to_confirmation (GTK_WINDOW (window),
3070 TNY_FOLDER (folder_store),
3074 if (response == GTK_RESPONSE_OK) {
3075 /* Launch notification */
3076 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3077 _CS("ckct_nw_pasting"));
3078 if (inf_note != NULL) {
3079 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3080 gtk_widget_show (GTK_WIDGET(inf_note));
3083 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3084 modest_mail_operation_xfer_msgs (mail_op,
3086 TNY_FOLDER (folder_store),
3091 g_object_unref (mail_op);
3094 } else if (src_folder != NULL) {
3095 /* Launch notification */
3096 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3097 _CS("ckct_nw_pasting"));
3098 if (inf_note != NULL) {
3099 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3100 gtk_widget_show (GTK_WIDGET(inf_note));
3103 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3104 modest_mail_operation_xfer_folder (mail_op,
3114 g_object_unref (data);
3115 if (src_folder != NULL)
3116 g_object_unref (src_folder);
3117 if (folder_store != NULL)
3118 g_object_unref (folder_store);
3124 modest_ui_actions_on_select_all (GtkAction *action,
3125 ModestWindow *window)
3127 GtkWidget *focused_widget;
3129 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3130 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3131 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3132 } else if (GTK_IS_LABEL (focused_widget)) {
3133 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3134 } else if (GTK_IS_EDITABLE (focused_widget)) {
3135 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3136 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3137 GtkTextBuffer *buffer;
3138 GtkTextIter start, end;
3140 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3141 gtk_text_buffer_get_start_iter (buffer, &start);
3142 gtk_text_buffer_get_end_iter (buffer, &end);
3143 gtk_text_buffer_select_range (buffer, &start, &end);
3144 } else if (GTK_IS_HTML (focused_widget)) {
3145 gtk_html_select_all (GTK_HTML (focused_widget));
3146 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3147 GtkWidget *header_view = focused_widget;
3148 GtkTreeSelection *selection = NULL;
3150 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3151 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3152 MODEST_WIDGET_TYPE_HEADER_VIEW);
3155 /* Disable window dimming management */
3156 modest_window_disable_dimming (MODEST_WINDOW(window));
3158 /* Select all messages */
3159 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3160 gtk_tree_selection_select_all (selection);
3162 /* Set focuse on header view */
3163 gtk_widget_grab_focus (header_view);
3166 /* Enable window dimming management */
3167 modest_window_enable_dimming (MODEST_WINDOW(window));
3168 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3174 modest_ui_actions_on_mark_as_read (GtkAction *action,
3175 ModestWindow *window)
3177 g_return_if_fail (MODEST_IS_WINDOW(window));
3179 /* Mark each header as read */
3180 do_headers_action (window, headers_action_mark_as_read, NULL);
3184 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3185 ModestWindow *window)
3187 g_return_if_fail (MODEST_IS_WINDOW(window));
3189 /* Mark each header as read */
3190 do_headers_action (window, headers_action_mark_as_unread, NULL);
3194 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3195 GtkRadioAction *selected,
3196 ModestWindow *window)
3200 value = gtk_radio_action_get_current_value (selected);
3201 if (MODEST_IS_WINDOW (window)) {
3202 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3206 void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3207 GtkRadioAction *selected,
3208 ModestWindow *window)
3210 TnyHeaderFlags flags;
3211 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3213 flags = gtk_radio_action_get_current_value (selected);
3214 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3217 void modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3218 GtkRadioAction *selected,
3219 ModestWindow *window)
3223 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3225 file_format = gtk_radio_action_get_current_value (selected);
3226 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3231 modest_ui_actions_on_zoom_plus (GtkAction *action,
3232 ModestWindow *window)
3234 g_return_if_fail (MODEST_IS_WINDOW (window));
3236 modest_window_zoom_plus (MODEST_WINDOW (window));
3240 modest_ui_actions_on_zoom_minus (GtkAction *action,
3241 ModestWindow *window)
3243 g_return_if_fail (MODEST_IS_WINDOW (window));
3245 modest_window_zoom_minus (MODEST_WINDOW (window));
3249 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
3250 ModestWindow *window)
3252 ModestWindowMgr *mgr;
3253 gboolean fullscreen, active;
3254 g_return_if_fail (MODEST_IS_WINDOW (window));
3256 mgr = modest_runtime_get_window_mgr ();
3258 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3259 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3261 if (active != fullscreen) {
3262 modest_window_mgr_set_fullscreen_mode (mgr, active);
3263 gtk_window_present (GTK_WINDOW (window));
3268 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3269 ModestWindow *window)
3271 ModestWindowMgr *mgr;
3272 gboolean fullscreen;
3274 g_return_if_fail (MODEST_IS_WINDOW (window));
3276 mgr = modest_runtime_get_window_mgr ();
3277 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3278 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3280 gtk_window_present (GTK_WINDOW (window));
3284 * Used by modest_ui_actions_on_details to call do_headers_action
3287 headers_action_show_details (TnyHeader *header,
3288 ModestWindow *window,
3295 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3298 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3299 gtk_widget_show_all (dialog);
3300 gtk_dialog_run (GTK_DIALOG (dialog));
3302 gtk_widget_destroy (dialog);
3306 * Show the folder details in a ModestDetailsDialog widget
3309 show_folder_details (TnyFolder *folder,
3315 dialog = modest_details_dialog_new_with_folder (window, folder);
3318 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3319 gtk_widget_show_all (dialog);
3320 gtk_dialog_run (GTK_DIALOG (dialog));
3322 gtk_widget_destroy (dialog);
3326 * Show the header details in a ModestDetailsDialog widget
3329 modest_ui_actions_on_details (GtkAction *action,
3332 TnyList * headers_list;
3336 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3339 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3342 g_object_unref (msg);
3344 headers_list = get_selected_headers (win);
3348 iter = tny_list_create_iterator (headers_list);
3350 header = TNY_HEADER (tny_iterator_get_current (iter));
3352 headers_action_show_details (header, win, NULL);
3353 g_object_unref (header);
3356 g_object_unref (iter);
3357 g_object_unref (headers_list);
3359 } else if (MODEST_IS_MAIN_WINDOW (win)) {
3360 GtkWidget *folder_view, *header_view;
3362 /* Check which widget has the focus */
3363 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3364 MODEST_WIDGET_TYPE_FOLDER_VIEW);
3365 if (gtk_widget_is_focus (folder_view)) {
3366 TnyFolderStore *folder_store
3367 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3368 if (!folder_store) {
3369 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3372 /* Show only when it's a folder */
3373 /* This function should not be called for account items,
3374 * because we dim the menu item for them. */
3375 if (TNY_IS_FOLDER (folder_store)) {
3376 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3379 g_object_unref (folder_store);
3382 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3383 MODEST_WIDGET_TYPE_HEADER_VIEW);
3384 /* Show details of each header */
3385 do_headers_action (win, headers_action_show_details, header_view);
3391 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3392 ModestMsgEditWindow *window)
3394 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3396 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3400 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3401 ModestMsgEditWindow *window)
3403 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3405 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3409 modest_ui_actions_toggle_folders_view (GtkAction *action,
3410 ModestMainWindow *main_window)
3412 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3414 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3415 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3417 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3421 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
3422 ModestWindow *window)
3424 gboolean active, fullscreen = FALSE;
3425 ModestWindowMgr *mgr;
3427 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3429 /* Check if we want to toggle the toolbar vuew in fullscreen
3431 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
3432 "ViewShowToolbarFullScreen")) {
3436 /* Toggle toolbar */
3437 mgr = modest_runtime_get_window_mgr ();
3438 modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3442 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3443 ModestMsgEditWindow *window)
3445 modest_msg_edit_window_select_font (window);
3449 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3450 const gchar *display_name,
3453 /* Do not change the application name if the widget has not
3454 the focus. This callback could be called even if the folder
3455 view has not the focus, because the handled signal could be
3456 emitted when the folder view is redrawn */
3457 if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3459 gtk_window_set_title (window, display_name);
3461 gtk_window_set_title (window, " ");
3466 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3468 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3469 modest_msg_edit_window_select_contacts (window);
3473 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3475 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3476 modest_msg_edit_window_check_names (window, FALSE);
3480 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3482 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3483 GTK_WIDGET (user_data));
3487 * This function is used to track changes in the selection of the
3488 * folder view that is inside the "move to" dialog to enable/disable
3489 * the OK button because we do not want the user to select a
3490 * disallowed destination for a folder
3493 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3494 TnyFolderStore *folder_store,
3498 GtkWidget *dialog = NULL, *ok_button = NULL;
3499 GList *children = NULL;
3500 gboolean sensitive = TRUE, moving_folder = FALSE;
3501 GtkWidget *folder_view = NULL;
3506 /* Get the OK button */
3507 dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3511 children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3512 ok_button = GTK_WIDGET (children->next->next->data);
3513 g_list_free (children);
3516 if (MODEST_IS_MAIN_WINDOW (user_data)) {
3517 /* Get the widgets */
3518 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3519 MODEST_WIDGET_TYPE_FOLDER_VIEW);
3520 if (gtk_widget_is_focus (folder_view))
3521 moving_folder = TRUE;
3524 if (moving_folder) {
3525 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3527 /* Get the folder to move */
3528 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3530 /* Check that we're not moving to the same folder */
3531 if (TNY_IS_FOLDER (moved_folder)) {
3532 parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3533 if (parent == folder_store)
3535 g_object_unref (parent);
3538 if (sensitive && TNY_IS_ACCOUNT (folder_store)) {
3539 TnyAccount *local_account = NULL;
3540 ModestTnyAccountStore *account_store;
3542 account_store = modest_runtime_get_account_store ();
3543 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3545 /* Do not allow to move to an account unless it's the
3546 local folders account */
3547 if ((gpointer) local_account != (gpointer) folder_store)
3549 g_object_unref (local_account);
3552 if (sensitive && (moved_folder == folder_store)) {
3553 /* Do not allow to move to itself */
3556 g_object_unref (moved_folder);
3558 TnyHeader *header = NULL;
3559 TnyFolder *src_folder = NULL;
3561 /* Moving a message */
3562 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3563 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3564 src_folder = tny_header_get_folder (header);
3565 g_object_unref (header);
3568 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3571 /* Do not allow to move the msg to the same folder */
3572 /* Do not allow to move the msg to an account */
3573 if ((gpointer) src_folder == (gpointer) folder_store ||
3574 TNY_IS_ACCOUNT (folder_store))
3576 g_object_unref (src_folder);
3579 /* Set sensitivity of the OK button */
3580 gtk_widget_set_sensitive (ok_button, sensitive);
3584 create_move_to_dialog (GtkWindow *win,
3585 GtkWidget *folder_view,
3586 GtkWidget **tree_view)
3588 GtkWidget *dialog, *scroll;
3589 GtkWidget *new_button;
3591 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3593 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3596 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3597 /* We do this manually so GTK+ does not associate a response ID for
3599 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3600 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3601 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3603 /* Create scrolled window */
3604 scroll = gtk_scrolled_window_new (NULL, NULL);
3605 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
3606 GTK_POLICY_AUTOMATIC,
3607 GTK_POLICY_AUTOMATIC);
3609 /* Create folder view */
3610 *tree_view = modest_platform_create_folder_view (NULL);
3612 /* Track changes in the selection to disable the OK button
3613 whenever "Move to" is not possible */
3614 g_signal_connect (*tree_view,
3615 "folder_selection_changed",
3616 G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3619 /* Listen to clicks on New button */
3620 g_signal_connect (G_OBJECT (new_button),
3622 G_CALLBACK(create_move_to_dialog_on_new_folder),
3625 /* It could happen that we're trying to move a message from a
3626 window (msg window for example) after the main window was
3627 closed, so we can not just get the model of the folder
3629 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3630 const gchar *visible_id = NULL;
3632 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
3633 MODEST_FOLDER_VIEW(*tree_view));
3636 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3638 /* Show the same account than the one that is shown in the main window */
3639 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
3642 const gchar *active_account_name = NULL;
3643 ModestAccountMgr *mgr = NULL;
3644 ModestAccountData *acc_data = NULL;
3646 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
3647 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3649 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3650 mgr = modest_runtime_get_account_mgr ();
3651 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3653 /* Set the new visible & active account */
3654 if (acc_data && acc_data->store_account) {
3655 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3656 acc_data->store_account->account_name);
3657 modest_account_mgr_free_account_data (mgr, acc_data);
3661 /* Hide special folders */
3662 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3664 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3666 /* Add scroll to dialog */
3667 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
3668 scroll, TRUE, TRUE, 0);
3670 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3671 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3677 * Returns TRUE if at least one of the headers of the list belongs to
3678 * a message that has been fully retrieved.
3680 #if 0 /* no longer in use. delete in 2007.10 */
3682 has_retrieved_msgs (TnyList *list)
3685 gboolean found = FALSE;
3687 iter = tny_list_create_iterator (list);
3688 while (!tny_iterator_is_done (iter) && !found) {
3690 TnyHeaderFlags flags = 0;
3692 header = TNY_HEADER (tny_iterator_get_current (iter));
3694 flags = tny_header_get_flags (header);
3695 if (flags & TNY_HEADER_FLAG_CACHED)
3696 /* if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3699 g_object_unref (header);
3703 tny_iterator_next (iter);
3705 g_object_unref (iter);
3713 * Shows a confirmation dialog to the user when we're moving messages
3714 * from a remote server to the local storage. Returns the dialog
3715 * response. If it's other kind of movement the it always returns
3719 msgs_move_to_confirmation (GtkWindow *win,
3720 TnyFolder *dest_folder,
3724 gint response = GTK_RESPONSE_OK;
3726 /* If the destination is a local folder (or MMC folder )*/
3727 if (!modest_tny_folder_is_remote_folder (dest_folder)) {
3732 TnyFolder *src_folder = NULL;
3733 TnyIterator *iter = NULL;
3734 TnyHeader *header = NULL;
3736 /* get the device */
3738 device = modest_runtime_get_device ();
3740 is_online = tny_device_is_online (device);
3742 g_warning ("failed to get tny device"); /* should not happend */
3746 /* Get source folder */
3747 iter = tny_list_create_iterator (headers);
3748 header = TNY_HEADER (tny_iterator_get_current (iter));
3750 src_folder = tny_header_get_folder (header);
3751 g_object_unref (header);
3754 g_object_unref (iter);
3756 /* if no src_folder, message may be an attahcment */
3757 if (src_folder == NULL)
3758 return GTK_RESPONSE_CANCEL;
3760 /* If the source is a remote folder */
3761 if (!is_online && modest_tny_folder_is_remote_folder (src_folder)) {
3763 const gchar *message = NULL;
3764 message = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs",
3765 tny_list_get_length (headers));
3766 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3767 (const gchar *) message);
3769 response = GTK_RESPONSE_OK;
3771 g_object_unref (src_folder);
3780 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3782 ModestMsgViewWindow *self = NULL;
3784 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3785 self = MODEST_MSG_VIEW_WINDOW (object);
3787 if (!modest_msg_view_window_select_next_message (self))
3788 if (!modest_msg_view_window_select_previous_message (self))
3789 /* No more messages to view, so close this window */
3790 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3794 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
3797 GObject *win = modest_mail_operation_get_source (mail_op);
3798 const GError *error = NULL;
3799 const gchar *message = NULL;
3801 /* Get error message */
3802 error = modest_mail_operation_get_error (mail_op);
3803 if (error != NULL && error->message != NULL) {
3804 message = error->message;
3806 message = _("mail_in_ui_folder_move_target_error");
3809 /* Show notification dialog */
3810 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3811 g_object_unref (win);
3815 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op,
3818 GObject *win = modest_mail_operation_get_source (mail_op);
3819 const GError *error = modest_mail_operation_get_error (mail_op);
3821 g_return_if_fail (error != NULL);
3822 if (error->message != NULL)
3823 g_printerr ("modest: %s\n", error->message);
3825 g_printerr ("modest: unkonw error on send&receive operation");
3827 /* Show error message */
3828 /* if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3829 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3830 /* _CS("sfil_ib_unable_to_receive")); */
3832 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3833 /* _CS("sfil_ib_unable_to_send")); */
3834 g_object_unref (win);
3838 open_msg_for_purge_cb (ModestMailOperation *mail_op,
3845 gint pending_purges = 0;
3846 gboolean some_purged = FALSE;
3847 ModestWindow *win = MODEST_WINDOW (user_data);
3848 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3850 /* If there was any error */
3851 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3852 modest_window_mgr_unregister_header (mgr, header);
3856 /* Once the message has been retrieved for purging, we check if
3857 * it's all ok for purging */
3859 parts = tny_simple_list_new ();
3860 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3861 iter = tny_list_create_iterator (parts);
3863 while (!tny_iterator_is_done (iter)) {
3865 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3866 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3867 if (tny_mime_part_is_purged (part))
3874 g_object_unref (part);
3876 tny_iterator_next (iter);
3879 if (pending_purges>0) {
3881 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3883 if (response == GTK_RESPONSE_OK) {
3884 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3885 tny_iterator_first (iter);
3886 while (!tny_iterator_is_done (iter)) {
3889 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3890 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3891 tny_mime_part_set_purged (part);
3894 g_object_unref (part);
3896 tny_iterator_next (iter);
3899 tny_msg_rewrite_cache (msg);
3902 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3905 /* remove attachments */
3906 tny_iterator_first (iter);
3907 while (!tny_iterator_is_done (iter)) {
3910 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3912 /* One for the reference given by tny_iterator_get_current(): */
3913 g_object_unref (part);
3915 /* TODO: Is this meant to remove the attachment by doing another unref()?
3916 * Otherwise, this seems useless. */
3919 tny_iterator_next (iter);
3921 modest_window_mgr_unregister_header (mgr, header);
3923 g_object_unref (iter);
3924 g_object_unref (parts);
3928 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3929 ModestMainWindow *win)
3931 GtkWidget *header_view;
3932 TnyList *header_list;
3935 TnyHeaderFlags flags;
3936 ModestWindow *msg_view_window = NULL;
3939 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3941 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3942 MODEST_WIDGET_TYPE_HEADER_VIEW);
3944 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3946 if (tny_list_get_length (header_list) == 1) {
3947 iter = tny_list_create_iterator (header_list);
3948 header = TNY_HEADER (tny_iterator_get_current (iter));
3949 g_object_unref (iter);
3954 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3955 header, &msg_view_window);
3956 flags = tny_header_get_flags (header);
3957 if (!(flags & TNY_HEADER_FLAG_CACHED))
3960 if (msg_view_window != NULL)
3961 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3963 /* do nothing; uid was registered before, so window is probably on it's way */
3964 g_warning ("debug: header %p has already been registered", header);
3967 ModestMailOperation *mail_op = NULL;
3968 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3969 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3971 modest_ui_actions_get_msgs_full_error_handler,
3973 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3974 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3976 g_object_unref (mail_op);
3979 g_object_unref (header);
3981 g_object_unref (header_list);
3985 * Utility function that transfer messages from both the main window
3986 * and the msg view window when using the "Move to" dialog
3989 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3992 TnyList *headers = NULL;
3994 TnyAccount *dst_account = NULL;
3995 const gchar *proto_str = NULL;
3996 gboolean dst_is_pop = FALSE;
3998 if (!TNY_IS_FOLDER (dst_folder)) {
3999 modest_platform_information_banner (GTK_WIDGET (win),
4001 _CS("ckdg_ib_unable_to_move_to_current_location"));
4005 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4006 proto_str = tny_account_get_proto (dst_account);
4008 /* tinymail will return NULL for local folders it seems */
4009 dst_is_pop = proto_str &&
4010 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
4011 MODEST_PROTOCOL_STORE_POP);
4013 g_object_unref (dst_account);
4015 /* Get selected headers */
4016 headers = get_selected_headers (MODEST_WINDOW (win));
4019 modest_platform_information_banner (GTK_WIDGET (win),
4021 ngettext("mail_in_ui_folder_move_target_error",
4022 "mail_in_ui_folder_move_targets_error",
4023 tny_list_get_length (headers)));
4024 g_object_unref (headers);
4028 /* Ask for user confirmation */
4029 response = msgs_move_to_confirmation (GTK_WINDOW (win),
4030 TNY_FOLDER (dst_folder),
4034 /* Transfer messages */
4035 if (response == GTK_RESPONSE_OK) {
4036 ModestMailOperation *mail_op =
4037 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4039 modest_ui_actions_move_folder_error_handler,
4041 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4044 modest_mail_operation_xfer_msgs (mail_op,
4046 TNY_FOLDER (dst_folder),
4048 (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
4051 g_object_unref (G_OBJECT (mail_op));
4053 g_object_unref (headers);
4057 * UI handler for the "Move to" action when invoked from the
4061 modest_ui_actions_on_main_window_move_to (GtkAction *action,
4062 GtkWidget *folder_view,
4063 TnyFolderStore *dst_folder,
4064 ModestMainWindow *win)
4066 GtkWidget *header_view = NULL;
4067 ModestMailOperation *mail_op = NULL;
4068 TnyFolderStore *src_folder;
4070 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4072 /* Get the source folder */
4073 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4075 /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
4076 if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win),
4080 /* Get header view */
4082 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
4084 /* Get folder or messages to transfer */
4085 if (gtk_widget_is_focus (folder_view)) {
4086 GtkTreeSelection *sel;
4088 /* Allow only to transfer folders to the local root folder */
4089 if (TNY_IS_ACCOUNT (dst_folder) &&
4090 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
4093 /* Clean folder on header view before moving it */
4094 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4095 gtk_tree_selection_unselect_all (sel);
4097 if (TNY_IS_FOLDER (src_folder)) {
4099 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4101 modest_ui_actions_move_folder_error_handler,
4103 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4106 modest_mail_operation_xfer_folder (mail_op,
4107 TNY_FOLDER (src_folder),
4110 /* Unref mail operation */
4111 g_object_unref (G_OBJECT (mail_op));
4113 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4115 } else if (gtk_widget_is_focus (header_view)) {
4116 /* Transfer messages */
4117 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4122 g_object_unref (src_folder);
4127 * UI handler for the "Move to" action when invoked from the
4128 * ModestMsgViewWindow
4131 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
4132 TnyFolderStore *dst_folder,
4133 ModestMsgViewWindow *win)
4135 TnyHeader *header = NULL;
4136 TnyFolder *src_folder;
4138 /* Create header list */
4139 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
4140 src_folder = tny_header_get_folder(header);
4141 g_object_unref (header);
4143 /* Transfer the message */
4144 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
4145 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4147 g_object_unref (src_folder);
4151 modest_ui_actions_on_move_to (GtkAction *action,
4154 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4156 TnyFolderStore *dst_folder = NULL;
4157 ModestMainWindow *main_window;
4159 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4160 MODEST_IS_MSG_VIEW_WINDOW (win));
4162 /* Get the main window if exists */
4163 if (MODEST_IS_MAIN_WINDOW (win))
4164 main_window = MODEST_MAIN_WINDOW (win);
4167 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4169 /* Get the folder view widget if exists */
4171 folder_view = modest_main_window_get_child_widget (main_window,
4172 MODEST_WIDGET_TYPE_FOLDER_VIEW);
4176 /* Create and run the dialog */
4177 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4178 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4179 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4180 result = gtk_dialog_run (GTK_DIALOG(dialog));
4181 g_object_ref (tree_view);
4182 gtk_widget_destroy (dialog);
4184 if (result != GTK_RESPONSE_ACCEPT)
4187 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4188 /* Offer the connection dialog if necessary: */
4189 if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win),
4192 /* Do window specific stuff */
4193 if (MODEST_IS_MAIN_WINDOW (win))
4194 modest_ui_actions_on_main_window_move_to (action,
4197 MODEST_MAIN_WINDOW (win));
4199 modest_ui_actions_on_msg_view_window_move_to (action,
4201 MODEST_MSG_VIEW_WINDOW (win));
4204 g_object_unref (dst_folder);
4208 * Calls #HeadersFunc for each header already selected in the main
4209 * window or the message currently being shown in the msg view window
4212 do_headers_action (ModestWindow *win,
4216 TnyList *headers_list = NULL;
4217 TnyIterator *iter = NULL;
4218 TnyHeader *header = NULL;
4219 TnyFolder *folder = NULL;
4222 headers_list = get_selected_headers (win);
4226 /* Get the folder */
4227 iter = tny_list_create_iterator (headers_list);
4228 header = TNY_HEADER (tny_iterator_get_current (iter));
4230 folder = tny_header_get_folder (header);
4231 g_object_unref (header);
4234 /* Call the function for each header */
4235 while (!tny_iterator_is_done (iter)) {
4236 header = TNY_HEADER (tny_iterator_get_current (iter));
4237 func (header, win, user_data);
4238 g_object_unref (header);
4239 tny_iterator_next (iter);
4242 /* Trick: do a poke status in order to speed up the signaling
4244 tny_folder_poke_status (folder);
4247 g_object_unref (folder);
4248 g_object_unref (iter);
4249 g_object_unref (headers_list);
4253 modest_ui_actions_view_attachment (GtkAction *action,
4254 ModestWindow *window)
4256 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4257 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4259 /* not supported window for this action */
4260 g_return_if_reached ();
4265 modest_ui_actions_save_attachments (GtkAction *action,
4266 ModestWindow *window)
4268 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4269 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4271 /* not supported window for this action */
4272 g_return_if_reached ();
4277 modest_ui_actions_remove_attachments (GtkAction *action,
4278 ModestWindow *window)
4280 if (MODEST_IS_MAIN_WINDOW (window)) {
4281 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4282 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4283 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4285 /* not supported window for this action */
4286 g_return_if_reached ();
4291 modest_ui_actions_on_settings (GtkAction *action,
4296 dialog = modest_platform_get_global_settings_dialog ();
4297 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4298 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4299 gtk_widget_show_all (dialog);
4301 gtk_dialog_run (GTK_DIALOG (dialog));
4303 gtk_widget_destroy (dialog);
4307 modest_ui_actions_on_help (GtkAction *action,
4310 const gchar *help_id = NULL;
4312 if (MODEST_IS_MAIN_WINDOW (win)) {
4313 const gchar *action_name;
4314 action_name = gtk_action_get_name (action);
4316 if (!strcmp (action_name, "FolderViewCSMHelp") ||
4317 !strcmp (action_name, "HeaderViewCSMHelp")) {
4318 GtkWidget *folder_view;
4319 TnyFolderStore *folder_store;
4320 /* Get selected folder */
4321 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4322 MODEST_WIDGET_TYPE_FOLDER_VIEW);
4323 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4325 /* Switch help_id */
4326 if (TNY_IS_FOLDER (folder_store)) {
4327 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4328 case TNY_FOLDER_TYPE_NORMAL:
4329 help_id = "applications_email_managefolders";
4331 case TNY_FOLDER_TYPE_INBOX:
4332 help_id = "applications_email_inbox";
4334 case TNY_FOLDER_TYPE_OUTBOX:
4335 help_id = "applications_email_outbox";
4337 case TNY_FOLDER_TYPE_SENT:
4338 help_id = "applications_email_sent";
4340 case TNY_FOLDER_TYPE_DRAFTS:
4341 help_id = "applications_email_drafts";
4343 case TNY_FOLDER_TYPE_ARCHIVE:
4344 help_id = "applications_email_managefolders";
4347 help_id = "applications_email_managefolders";
4350 help_id = "applications_email_mainview";
4352 g_object_unref (folder_store);
4354 help_id = "applications_email_mainview";
4356 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4357 help_id = "applications_email_viewer";
4358 } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4359 help_id = "applications_email_editor";
4361 modest_platform_show_help (GTK_WINDOW (win), help_id);
4365 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4366 ModestWindow *window)
4368 ModestMailOperation *mail_op;
4372 headers = get_selected_headers (window);
4376 /* Create mail operation */
4377 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4379 modest_ui_actions_get_msgs_full_error_handler,
4381 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4382 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4385 g_object_unref (headers);
4386 g_object_unref (mail_op);
4390 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4391 ModestWindow *window)
4393 g_return_if_fail (MODEST_IS_WINDOW (window));
4396 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4400 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4401 ModestWindow *window)
4403 g_return_if_fail (MODEST_IS_WINDOW (window));
4406 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4410 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4411 ModestWindow *window)
4413 g_return_if_fail (MODEST_IS_WINDOW (window));
4416 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4420 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4421 ModestWindow *window)
4423 g_return_if_fail (MODEST_IS_WINDOW (window));
4426 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4430 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4431 ModestWindow *window)
4433 g_return_if_fail (MODEST_IS_WINDOW (window));
4436 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4440 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4441 ModestWindow *window)
4443 g_return_if_fail (MODEST_IS_WINDOW (window));
4446 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4450 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4451 ModestWindow *window)
4453 g_return_if_fail (MODEST_IS_WINDOW (window));
4456 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4460 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4461 ModestWindow *window)
4463 g_return_if_fail (MODEST_IS_WINDOW (window));
4466 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4470 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4472 g_return_if_fail (MODEST_IS_WINDOW (window));
4475 modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");
4479 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4481 g_return_if_fail (MODEST_IS_WINDOW (window));
4483 modest_platform_show_search_messages (GTK_WINDOW (window));
4487 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4489 g_return_if_fail (MODEST_IS_WINDOW (win));
4490 modest_platform_show_addressbook (GTK_WINDOW (win));
4495 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4496 ModestWindow *window)
4498 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4500 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4504 _on_send_receive_progress_changed (ModestMailOperation *mail_op,
4505 ModestMailOperationState *state,
4508 g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4510 /* Set send/receive operation finished */
4511 if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4512 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));