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 gboolean download_uncached_messages (TnyList *header_list,
146 /* static gint msgs_move_to_confirmation (GtkWindow *win, */
147 /* TnyFolder *dest_folder, */
148 /* gboolean delete, */
149 /* TnyList *headers); */
152 /* Show the account creation wizard dialog.
153 * returns: TRUE if an account was created. FALSE if the user cancelled.
156 modest_run_account_setup_wizard (ModestWindow *win)
158 gboolean result = FALSE;
161 wizard = modest_window_mgr_get_easysetup_dialog
162 (modest_runtime_get_window_mgr());
164 /* old wizard is active already; present it and
165 * act as if the user cancelled the non-existing
168 printf ("wizard already active\n");
171 /* there is no such wizard yet */
172 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
173 modest_window_mgr_set_easysetup_dialog
174 (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
178 /* always present a main window in the background
179 * we do it here, so we cannot end up with to wizards (as this
180 * function might be called in modest_window_mgr_get_main_window as well */
182 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
184 /* make sure the mainwindow is visible */
185 gtk_widget_show_all (GTK_WIDGET(win));
186 gtk_window_present (GTK_WINDOW(win));
189 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
191 /* Don't make this a modal window, because secondary windows will then
192 * be unusable, freezing the UI: */
193 /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
195 gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
196 if (dialog_response == GTK_RESPONSE_CANCEL)
199 /* Check whether an account was created: */
200 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
203 gtk_widget_destroy (GTK_WIDGET (wizard));
205 /* clear it from the window mgr */
206 modest_window_mgr_set_easysetup_dialog
207 (modest_runtime_get_window_mgr(), NULL);
214 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
217 const gchar *authors[] = {
218 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
221 about = gtk_about_dialog_new ();
222 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
223 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
224 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
225 _("Copyright (c) 2006, Nokia Corporation\n"
226 "All rights reserved."));
227 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
228 _("a modest e-mail client\n\n"
229 "design and implementation: Dirk-Jan C. Binnema\n"
230 "contributions from the fine people at KC and Ig\n"
231 "uses the tinymail email framework written by Philip van Hoof"));
232 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
233 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
234 gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
235 gtk_window_set_modal (GTK_WINDOW (about), TRUE);
237 gtk_dialog_run (GTK_DIALOG (about));
238 gtk_widget_destroy(about);
242 * Gets the list of currently selected messages. If the win is the
243 * main window, then it returns a newly allocated list of the headers
244 * selected in the header view. If win is the msg view window, then
245 * the value returned is a list with just a single header.
247 * The caller of this funcion must free the list.
250 get_selected_headers (ModestWindow *win)
252 if (MODEST_IS_MAIN_WINDOW(win)) {
253 GtkWidget *header_view;
255 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
256 MODEST_WIDGET_TYPE_HEADER_VIEW);
257 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
259 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
260 /* for MsgViewWindows, we simply return a list with one element */
262 TnyList *list = NULL;
264 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
265 if (header != NULL) {
266 list = tny_simple_list_new ();
267 tny_list_prepend (list, G_OBJECT(header));
268 g_object_unref (G_OBJECT(header));
278 headers_action_mark_as_read (TnyHeader *header,
282 TnyHeaderFlags flags;
284 g_return_if_fail (TNY_IS_HEADER(header));
286 flags = tny_header_get_flags (header);
287 if (flags & TNY_HEADER_FLAG_SEEN) return;
288 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
292 headers_action_mark_as_unread (TnyHeader *header,
296 TnyHeaderFlags flags;
298 g_return_if_fail (TNY_IS_HEADER(header));
300 flags = tny_header_get_flags (header);
301 if (flags & TNY_HEADER_FLAG_SEEN) {
302 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
306 /** A convenience method, because deleting a message is
307 * otherwise complicated, and it's best to change it in one place
310 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
312 ModestMailOperation *mail_op = NULL;
313 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE,
314 win ? G_OBJECT(win) : NULL);
315 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
318 /* Always delete. TODO: Move to trash still not supported */
319 modest_mail_operation_remove_msg (mail_op, header, FALSE);
320 g_object_unref (G_OBJECT (mail_op));
324 headers_action_delete (TnyHeader *header,
328 modest_do_message_delete (header, win);
331 /** After deleing a message that is currently visible in a window,
332 * show the next message from the list, or close the window if there are no more messages.
334 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
336 /* Close msg view window or select next */
337 if (modest_msg_view_window_last_message_selected (win) &&
338 modest_msg_view_window_first_message_selected (win)) {
339 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
341 if (!modest_msg_view_window_select_next_message (win)) {
343 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
349 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
351 TnyList *header_list = NULL;
352 TnyIterator *iter = NULL;
353 TnyHeader *header = NULL;
354 gchar *message = NULL;
357 ModestWindowMgr *mgr;
358 GtkWidget *header_view = NULL;
360 g_return_if_fail (MODEST_IS_WINDOW(win));
362 /* Check first if the header view has the focus */
363 if (MODEST_IS_MAIN_WINDOW (win)) {
365 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
366 MODEST_WIDGET_TYPE_HEADER_VIEW);
367 if (!gtk_widget_is_focus (header_view))
371 /* Get the headers, either from the header view (if win is the main window),
372 * or from the message view window: */
373 header_list = get_selected_headers (win);
374 if (!header_list) return;
376 /* Check if any of the headers are already opened, or in the process of being opened */
377 if (MODEST_IS_MAIN_WINDOW (win)) {
379 iter = tny_list_create_iterator (header_list);
381 mgr = modest_runtime_get_window_mgr ();
382 while (!tny_iterator_is_done (iter) && !found) {
383 header = TNY_HEADER (tny_iterator_get_current (iter));
385 found = modest_window_mgr_find_registered_header (mgr, header, NULL);
386 g_object_unref (header);
389 tny_iterator_next (iter);
391 g_object_unref (iter);
396 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
397 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
399 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
403 g_object_unref (header_list);
409 if (tny_list_get_length(header_list) == 1) {
410 iter = tny_list_create_iterator (header_list);
411 header = TNY_HEADER (tny_iterator_get_current (iter));
413 desc = g_strdup_printf ("%s", tny_header_get_subject (header));
414 g_object_unref (header);
417 g_object_unref (iter);
419 message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
420 tny_list_get_length(header_list)), desc);
422 /* Confirmation dialog */
423 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
427 if (response == GTK_RESPONSE_OK) {
428 ModestWindow *main_window = NULL;
429 ModestWindowMgr *mgr = NULL;
430 GtkTreeModel *model = NULL;
431 GtkTreeSelection *sel = NULL;
432 GList *sel_list = NULL, *tmp = NULL;
433 GtkTreeRowReference *row_reference = NULL;
434 GtkTreePath *next_path = NULL;
435 TnyFolder *folder = NULL;
438 /* Find last selected row */
439 if (MODEST_IS_MAIN_WINDOW (win)) {
440 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
441 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
442 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
443 for (tmp=sel_list; tmp; tmp=tmp->next) {
444 if (tmp->next == NULL) {
445 next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
446 gtk_tree_path_next (next_path);
447 row_reference = gtk_tree_row_reference_new (model, next_path);
448 gtk_tree_path_free (next_path);
453 /* Remove each header. If it's a view window header_view == NULL */
454 do_headers_action (win, headers_action_delete, header_view);
456 /* refresh the header view (removing marked-as-deleted)*/
457 modest_header_view_refilter (MODEST_HEADER_VIEW(header_view));
459 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
460 modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
462 /* Get main window */
463 mgr = modest_runtime_get_window_mgr ();
464 main_window = modest_window_mgr_get_main_window (mgr);
467 /* Move cursor to next row */
470 /* Select next row */
471 if (gtk_tree_row_reference_valid (row_reference)) {
472 next_path = gtk_tree_row_reference_get_path (row_reference);
473 gtk_tree_selection_select_path (sel, next_path);
474 gtk_tree_path_free (next_path);
476 if (row_reference != NULL)
477 gtk_tree_row_reference_free (row_reference);
480 /* Get folder from first header and sync it */
481 iter = tny_list_create_iterator (header_list);
482 header = TNY_HEADER (tny_iterator_get_current (iter));
483 folder = tny_header_get_folder (header);
484 if (TNY_IS_CAMEL_IMAP_FOLDER (folder))
485 /* tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* FALSE --> don't expunge *\/ */
486 tny_folder_sync (folder, FALSE, &err); /* FALSE --> don't expunge */
487 else if (TNY_IS_CAMEL_POP_FOLDER (folder))
488 /* tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* TRUE --> dont expunge *\/ */
489 tny_folder_sync (folder, TRUE, &err); /* TRUE --> expunge */
492 /* tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /\* TRUE --> expunge *\/ */
493 tny_folder_sync (folder, TRUE, &err); /* TRUE --> expunge */
496 printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
500 g_object_unref (header);
501 g_object_unref (iter);
502 g_object_unref (folder);
504 /* Update toolbar dimming state */
505 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
508 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
509 g_list_free (sel_list);
515 g_object_unref (header_list);
521 /* delete either message or folder, based on where we are */
523 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
525 g_return_if_fail (MODEST_IS_WINDOW(win));
527 /* Check first if the header view has the focus */
528 if (MODEST_IS_MAIN_WINDOW (win)) {
530 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
531 MODEST_WIDGET_TYPE_FOLDER_VIEW);
532 if (gtk_widget_is_focus (w)) {
533 modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
537 modest_ui_actions_on_delete_message (action, win);
543 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
545 #ifdef MODEST_PLATFORM_MAEMO
546 modest_osso_save_state();
547 #endif /* MODEST_PLATFORM_MAEMO */
549 g_debug ("closing down, clearing %d item(s) from operation queue",
550 modest_mail_operation_queue_num_elements
551 (modest_runtime_get_mail_operation_queue()));
553 /* cancel all outstanding operations */
554 modest_mail_operation_queue_cancel_all
555 (modest_runtime_get_mail_operation_queue());
557 g_debug ("queue has been cleared");
559 /* note: when modest-tny-account-store is finalized,
560 it will automatically set all network connections
567 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
571 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
573 /* if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
574 /* gtk_widget_destroy (GTK_WIDGET (win)); */
575 /* } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
576 /* gboolean ret_value; */
577 /* g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
578 /* } else if (MODEST_IS_WINDOW (win)) { */
579 /* gtk_widget_destroy (GTK_WIDGET (win)); */
581 /* g_return_if_reached (); */
586 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
588 GtkClipboard *clipboard = NULL;
589 gchar *selection = NULL;
591 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
592 selection = gtk_clipboard_wait_for_text (clipboard);
594 /* Question: why is the clipboard being used here?
595 * It doesn't really make a lot of sense. */
599 modest_address_book_add_address (selection);
605 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
607 /* This is currently only implemented for Maemo */
608 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
609 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
610 modest_run_account_setup_wizard (win);
613 /* Show the list of accounts: */
614 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
615 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
617 /* Don't make this a modal window, because secondary windows will then
618 * be unusable, freezing the UI: */
619 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
620 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win);
623 GtkWidget *dialog, *label;
625 /* Create the widgets */
627 dialog = gtk_dialog_new_with_buttons ("Message",
629 GTK_DIALOG_DESTROY_WITH_PARENT,
633 label = gtk_label_new ("Hello World!");
635 /* Ensure that the dialog box is destroyed when the user responds. */
637 g_signal_connect_swapped (dialog, "response",
638 G_CALLBACK (gtk_widget_destroy),
641 /* Add the label, and show everything we've added to the dialog. */
643 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
645 gtk_widget_show_all (dialog);
646 #endif /* MODEST_PLATFORM_MAEMO */
650 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
652 ModestWindow *main_window = MODEST_WINDOW (user_data);
654 /* Save any changes. */
655 modest_connection_specific_smtp_window_save_server_accounts (
656 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window),
657 modest_window_get_active_account (main_window));
658 gtk_widget_destroy (GTK_WIDGET (window));
664 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
666 /* This is currently only implemented for Maemo,
667 * because it requires an API (libconic) to detect different connection
670 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
672 /* Create the window if necessary: */
673 const gchar *active_account_name = modest_window_get_active_account (win);
675 /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
676 * or show the default account?
677 * If we show the default account then the account name should be shown in
678 * the window when we show it. */
679 if (!active_account_name) {
680 g_warning ("%s: No account is active.", __FUNCTION__);
684 GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
685 modest_connection_specific_smtp_window_fill_with_connections (
686 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
687 modest_runtime_get_account_mgr(),
688 active_account_name);
690 /* Show the window: */
691 gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
692 gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
693 gtk_widget_show (specific_window);
695 /* Save changes when the window is hidden: */
696 g_signal_connect (specific_window, "hide",
697 G_CALLBACK (on_smtp_servers_window_hide), win);
698 #endif /* MODEST_PLATFORM_MAEMO */
702 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
704 ModestWindow *msg_win = NULL;
706 TnyFolder *folder = NULL;
707 gchar *account_name = NULL;
708 gchar *from_str = NULL;
709 /* GError *err = NULL; */
710 TnyAccount *account = NULL;
711 ModestWindowMgr *mgr;
712 gchar *signature = NULL, *blank_and_signature = NULL;
714 /* if there are no accounts yet, just show the wizard */
715 if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
716 const gboolean created = modest_run_account_setup_wizard (win);
721 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
723 account_name = g_strdup (modest_window_get_active_account (win));
725 g_printerr ("modest: no account found\n");
729 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
731 TNY_ACCOUNT_TYPE_STORE);
733 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
737 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
739 g_printerr ("modest: failed get from string for '%s'\n", account_name);
743 gboolean use_signature = FALSE;
744 signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
747 blank_and_signature = g_strconcat ("\n", signature, NULL);
749 blank_and_signature = g_strdup ("");
754 msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
756 g_printerr ("modest: failed to create new msg\n");
760 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
762 g_printerr ("modest: failed to find Drafts folder\n");
767 /* Create and register edit window */
768 /* This is destroyed by TODO. */
769 msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
770 mgr = modest_runtime_get_window_mgr ();
771 modest_window_mgr_register_window (mgr, msg_win);
774 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
776 gtk_widget_show_all (GTK_WIDGET (msg_win));
779 g_free (account_name);
781 g_free (blank_and_signature);
783 g_object_unref (msg_win);
785 g_object_unref (G_OBJECT(account));
787 g_object_unref (G_OBJECT(msg));
789 g_object_unref (G_OBJECT(folder));
793 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
797 ModestMailOperationStatus status;
799 /* If there is no message or the operation was not successful */
800 status = modest_mail_operation_get_status (mail_op);
801 if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
803 /* Remove the header from the preregistered uids */
804 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
814 open_msg_cb (ModestMailOperation *mail_op,
819 ModestWindowMgr *mgr = NULL;
820 ModestWindow *parent_win = NULL;
821 ModestWindow *win = NULL;
822 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
823 gchar *account = NULL;
826 /* Do nothing if there was any problem with the mail
827 operation. The error will be shown by the error_handler of
828 the mail operation */
829 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
833 parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
834 folder = tny_header_get_folder (header);
836 /* Mark header as read */
837 headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
840 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
842 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
844 /* Gets folder type (OUTBOX headers will be opened in edit window */
845 if (modest_tny_folder_is_local_folder (folder))
846 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
848 /* If the header is in the drafts folder then open the editor,
849 else the message view window */
850 if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
851 (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
852 /* we cannot edit without a valid account... */
853 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
854 const gboolean created = modest_run_account_setup_wizard(parent_win);
858 win = modest_msg_edit_window_new (msg, account, TRUE);
861 gchar *uid = modest_tny_folder_get_header_unique_id (header);
863 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
864 GtkWidget *header_view;
865 GtkTreeSelection *sel;
866 GList *sel_list = NULL;
869 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
870 MODEST_WIDGET_TYPE_HEADER_VIEW);
872 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
873 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
875 if (sel_list != NULL) {
876 GtkTreeRowReference *row_reference;
878 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
879 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
880 g_list_free (sel_list);
882 win = modest_msg_view_window_new_with_header_model (
883 msg, account, (const gchar*) uid,
884 model, row_reference);
885 gtk_tree_row_reference_free (row_reference);
887 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
890 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
895 /* Register and show new window */
897 mgr = modest_runtime_get_window_mgr ();
898 modest_window_mgr_register_window (mgr, win);
899 g_object_unref (win);
900 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
901 gtk_widget_show_all (GTK_WIDGET(win));
904 /* Update toolbar dimming state */
905 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
906 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
912 g_object_unref (parent_win);
913 g_object_unref (folder);
917 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
921 GObject *win = modest_mail_operation_get_source (mail_op);
923 error = modest_mail_operation_get_error (mail_op);
924 printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
926 if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
928 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
931 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
932 _("mail_ni_ui_folder_get_msg_folder_error"));
936 g_object_unref (win);
940 * This function is used by both modest_ui_actions_on_open and
941 * modest_ui_actions_on_header_activated. This way we always do the
942 * same when trying to open messages.
945 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
947 ModestWindowMgr *mgr = NULL;
948 TnyIterator *iter = NULL;
949 ModestMailOperation *mail_op = NULL;
950 TnyList *not_opened_headers = NULL;
951 TnyHeaderFlags flags = 0;
953 g_return_if_fail (headers != NULL);
955 /* Check that only one message is selected for opening */
956 if (tny_list_get_length (headers) != 1) {
957 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
958 _("mcen_ib_select_one_message"));
963 /* Look if we already have a message view for each header. If
964 true, then remove the header from the list of headers to
966 mgr = modest_runtime_get_window_mgr ();
967 iter = tny_list_create_iterator (headers);
968 not_opened_headers = tny_simple_list_new ();
970 while (!tny_iterator_is_done (iter)) {
972 ModestWindow *window = NULL;
973 TnyHeader *header = NULL;
974 gboolean found = FALSE;
976 header = TNY_HEADER (tny_iterator_get_current (iter));
978 flags = tny_header_get_flags (header);
981 found = modest_window_mgr_find_registered_header (mgr, header, &window);
983 /* Do not open again the message and present the
984 window to the user */
987 gtk_window_present (GTK_WINDOW (window));
989 /* the header has been registered already, we don't do
990 * anything but wait for the window to come up*/
991 g_debug ("header %p already registered, waiting for window", header);
993 tny_list_append (not_opened_headers, G_OBJECT (header));
997 g_object_unref (header);
999 tny_iterator_next (iter);
1001 g_object_unref (iter);
1004 /* If some messages would have to be downloaded, ask the user to
1005 * make a connection. It's generally easier to do this here (in the mainloop)
1006 * than later in a thread:
1008 if (tny_list_get_length (not_opened_headers) > 0) {
1010 gboolean found = FALSE;
1012 iter = tny_list_create_iterator (not_opened_headers);
1013 while (!tny_iterator_is_done (iter) && !found) {
1014 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1015 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1018 tny_iterator_next (iter);
1020 g_object_unref (header);
1022 g_object_unref (iter);
1024 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1025 g_object_unref (not_opened_headers);
1030 /* Register the headers before actually creating the windows: */
1031 TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1032 while (!tny_iterator_is_done (iter_not_opened)) {
1033 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1035 modest_window_mgr_register_header (mgr, header);
1036 g_object_unref (header);
1039 tny_iterator_next (iter_not_opened);
1041 g_object_unref (iter_not_opened);
1042 iter_not_opened = NULL;
1044 /* Open each message */
1045 if (tny_list_get_length (not_opened_headers) > 0) {
1046 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1048 modest_ui_actions_get_msgs_full_error_handler,
1050 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1051 if (tny_list_get_length (not_opened_headers) > 1) {
1052 modest_mail_operation_get_msgs_full (mail_op,
1058 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1059 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1060 modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1061 g_object_unref (header);
1062 g_object_unref (iter);
1064 g_object_unref (mail_op);
1068 if (not_opened_headers != NULL)
1069 g_object_unref (not_opened_headers);
1073 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1078 headers = get_selected_headers (win);
1083 _modest_ui_actions_open (headers, win);
1085 g_object_unref(headers);
1090 free_reply_forward_helper (gpointer data)
1092 ReplyForwardHelper *helper;
1094 helper = (ReplyForwardHelper *) data;
1095 g_free (helper->account_name);
1096 g_slice_free (ReplyForwardHelper, helper);
1100 reply_forward_cb (ModestMailOperation *mail_op,
1106 ReplyForwardHelper *rf_helper;
1107 ModestWindow *msg_win = NULL;
1108 ModestEditType edit_type;
1110 TnyAccount *account = NULL;
1111 ModestWindowMgr *mgr = NULL;
1112 gchar *signature = NULL;
1114 /* If there was any error. The mail operation could be NULL,
1115 this means that we already have the message downloaded and
1116 that we didn't do a mail operation to retrieve it */
1117 if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1120 g_return_if_fail (user_data != NULL);
1121 rf_helper = (ReplyForwardHelper *) user_data;
1123 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1124 rf_helper->account_name);
1125 if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1126 rf_helper->account_name,
1127 MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1128 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1129 rf_helper->account_name,
1130 MODEST_ACCOUNT_SIGNATURE, FALSE);
1133 /* Create reply mail */
1134 switch (rf_helper->action) {
1137 modest_tny_msg_create_reply_msg (msg, header, from, signature,
1138 rf_helper->reply_forward_type,
1139 MODEST_TNY_MSG_REPLY_MODE_SENDER);
1141 case ACTION_REPLY_TO_ALL:
1143 modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1144 MODEST_TNY_MSG_REPLY_MODE_ALL);
1145 edit_type = MODEST_EDIT_TYPE_REPLY;
1147 case ACTION_FORWARD:
1149 modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1150 edit_type = MODEST_EDIT_TYPE_FORWARD;
1153 g_return_if_reached ();
1160 g_printerr ("modest: failed to create message\n");
1164 account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1165 rf_helper->account_name,
1166 TNY_ACCOUNT_TYPE_STORE);
1168 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1172 /* Create and register the windows */
1173 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1174 mgr = modest_runtime_get_window_mgr ();
1175 modest_window_mgr_register_window (mgr, msg_win);
1177 if (rf_helper->parent_window != NULL) {
1178 gdouble parent_zoom;
1180 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1181 modest_window_set_zoom (msg_win, parent_zoom);
1184 /* Show edit window */
1185 gtk_widget_show_all (GTK_WIDGET (msg_win));
1189 g_object_unref (msg_win);
1191 g_object_unref (G_OBJECT (new_msg));
1193 g_object_unref (G_OBJECT (account));
1194 /* g_object_unref (msg); */
1195 free_reply_forward_helper (rf_helper);
1199 * Checks a list of headers. If any of them are not currently
1200 * downloaded (CACHED) then it asks the user for permission to
1203 * Returns FALSE if the user does not want to download the
1204 * messages. Returns TRUE if the user allowed the download or if all
1205 * of them are currently downloaded
1208 download_uncached_messages (TnyList *header_list,
1213 gint uncached_messages = 0;
1215 iter = tny_list_create_iterator (header_list);
1216 while (!tny_iterator_is_done (iter)) {
1219 header = TNY_HEADER (tny_iterator_get_current (iter));
1221 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1222 uncached_messages ++;
1223 g_object_unref (header);
1226 tny_iterator_next (iter);
1228 g_object_unref (iter);
1230 /* Ask for user permission to download the messages */
1232 if (uncached_messages > 0) {
1233 gboolean download = TRUE;
1234 if (!tny_device_is_online (modest_runtime_get_device())) {
1235 GtkResponseType response =
1236 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1237 ngettext("mcen_nc_get_msg",
1239 uncached_messages));
1240 if (response == GTK_RESPONSE_CANCEL) download = FALSE;
1243 /* If a download will be necessary, make sure that we have a connection: */
1244 retval = modest_platform_connect_and_wait(win, NULL);
1254 * Common code for the reply and forward actions
1257 reply_forward (ReplyForwardAction action, ModestWindow *win)
1259 ModestMailOperation *mail_op = NULL;
1260 TnyList *header_list = NULL;
1261 ReplyForwardHelper *rf_helper = NULL;
1262 guint reply_forward_type;
1263 gboolean continue_download = TRUE;
1264 gboolean do_retrieve = TRUE;
1266 g_return_if_fail (MODEST_IS_WINDOW(win));
1268 /* we need an account when editing */
1269 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1270 const gboolean created = modest_run_account_setup_wizard (win);
1275 header_list = get_selected_headers (win);
1279 reply_forward_type =
1280 modest_conf_get_int (modest_runtime_get_conf (),
1281 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1284 /* Check that the messages have been previously downloaded */
1285 do_retrieve = (action == ACTION_FORWARD) || (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1287 continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
1288 if (!continue_download) {
1289 g_object_unref (header_list);
1293 /* We assume that we can only select messages of the
1294 same folder and that we reply all of them from the
1295 same account. In fact the interface currently only
1296 allows single selection */
1299 rf_helper = g_slice_new0 (ReplyForwardHelper);
1300 rf_helper->reply_forward_type = reply_forward_type;
1301 rf_helper->action = action;
1302 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1304 if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1305 rf_helper->parent_window = GTK_WIDGET (win);
1306 if (!rf_helper->account_name)
1307 rf_helper->account_name =
1308 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1310 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1313 /* Get header and message. Do not free them here, the
1314 reply_forward_cb must do it */
1315 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1316 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1317 if (!msg || !header) {
1319 g_object_unref (msg);
1320 g_printerr ("modest: no message found\n");
1323 reply_forward_cb (NULL, header, msg, rf_helper);
1326 g_object_unref (header);
1331 /* Only reply/forward to one message */
1332 iter = tny_list_create_iterator (header_list);
1333 header = TNY_HEADER (tny_iterator_get_current (iter));
1334 g_object_unref (iter);
1337 /* Retrieve messages */
1339 mail_op = modest_mail_operation_new_with_error_handling (
1340 MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1342 modest_ui_actions_get_msgs_full_error_handler,
1344 modest_mail_operation_queue_add (
1345 modest_runtime_get_mail_operation_queue (), mail_op);
1347 modest_mail_operation_get_msg (mail_op,
1352 g_object_unref(mail_op);
1354 /* we put a ref here to prevent double unref as the reply
1355 * forward callback unrefs the header at its end */
1356 reply_forward_cb (NULL, header, NULL, rf_helper);
1360 g_object_unref (header);
1366 g_object_unref (header_list);
1370 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1372 g_return_if_fail (MODEST_IS_WINDOW(win));
1374 reply_forward (ACTION_REPLY, win);
1378 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1380 g_return_if_fail (MODEST_IS_WINDOW(win));
1382 reply_forward (ACTION_FORWARD, win);
1386 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1388 g_return_if_fail (MODEST_IS_WINDOW(win));
1390 reply_forward (ACTION_REPLY_TO_ALL, win);
1394 modest_ui_actions_on_next (GtkAction *action,
1395 ModestWindow *window)
1397 if (MODEST_IS_MAIN_WINDOW (window)) {
1398 GtkWidget *header_view;
1400 header_view = modest_main_window_get_child_widget (
1401 MODEST_MAIN_WINDOW(window),
1402 MODEST_WIDGET_TYPE_HEADER_VIEW);
1406 modest_header_view_select_next (
1407 MODEST_HEADER_VIEW(header_view));
1408 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1409 modest_msg_view_window_select_next_message (
1410 MODEST_MSG_VIEW_WINDOW (window));
1412 g_return_if_reached ();
1417 modest_ui_actions_on_prev (GtkAction *action,
1418 ModestWindow *window)
1420 g_return_if_fail (MODEST_IS_WINDOW(window));
1422 if (MODEST_IS_MAIN_WINDOW (window)) {
1423 GtkWidget *header_view;
1424 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1425 MODEST_WIDGET_TYPE_HEADER_VIEW);
1429 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
1430 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1431 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1433 g_return_if_reached ();
1438 modest_ui_actions_on_sort (GtkAction *action,
1439 ModestWindow *window)
1441 g_return_if_fail (MODEST_IS_WINDOW(window));
1443 if (MODEST_IS_MAIN_WINDOW (window)) {
1444 GtkWidget *header_view;
1445 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1446 MODEST_WIDGET_TYPE_HEADER_VIEW);
1448 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1453 /* Show sorting dialog */
1454 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
1459 new_messages_arrived (ModestMailOperation *self,
1463 ModestMainWindow *win = NULL;
1464 GtkWidget *folder_view = NULL;
1465 TnyFolderStore *folder = NULL;
1466 gboolean folder_empty = FALSE;
1468 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1469 win = MODEST_MAIN_WINDOW (user_data);
1471 /* Set contents style of headers view */
1472 if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1473 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1474 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1475 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1478 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1481 modest_main_window_set_contents_style (win,
1482 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1485 /* Notify new messages have been downloaded */
1486 if (new_messages > 0)
1487 modest_platform_on_new_msg ();
1491 * This function performs the send & receive required actions. The
1492 * window is used to create the mail operation. Typically it should
1493 * always be the main window, but we pass it as argument in order to
1497 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1499 gchar *acc_name = NULL;
1500 ModestMailOperation *mail_op;
1502 /* If no account name was provided then get the current account, and if
1503 there is no current account then pick the default one: */
1504 if (!account_name) {
1505 acc_name = g_strdup (modest_window_get_active_account(win));
1507 acc_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1509 g_printerr ("modest: cannot get default account\n");
1513 acc_name = g_strdup (account_name);
1516 /* Set send/receive operation in progress */
1517 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1519 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1521 modest_ui_actions_send_receive_error_handler,
1524 g_signal_connect (G_OBJECT(mail_op), "progress-changed",
1525 G_CALLBACK (_on_send_receive_progress_changed),
1528 /* Send & receive. */
1529 /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1530 /* Receive and then send. The operation is tagged initially as
1531 a receive operation because the account update performs a
1532 receive and then a send. The operation changes its type
1533 internally, so the progress objects will receive the proper
1534 progress information */
1535 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1536 modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1537 g_object_unref (G_OBJECT (mail_op));
1545 modest_ui_actions_do_cancel_send (const gchar *account_name,
1548 TnyTransportAccount *transport_account;
1549 TnySendQueue *send_queue = NULL;
1550 GError *error = NULL;
1552 /* Get transport account */
1554 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1555 (modest_runtime_get_account_store(),
1557 TNY_ACCOUNT_TYPE_TRANSPORT));
1558 if (!transport_account) {
1559 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1564 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1565 if (!TNY_IS_SEND_QUEUE(send_queue)) {
1566 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1567 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1568 "modest: could not find send queue for account\n");
1570 /* Keeep messages in outbox folder */
1571 tny_send_queue_cancel (send_queue, FALSE, &error);
1575 if (transport_account != NULL)
1576 g_object_unref (G_OBJECT (transport_account));
1580 modest_ui_actions_cancel_send_all (ModestWindow *win)
1582 GSList *account_names, *iter;
1584 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1587 iter = account_names;
1589 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1590 iter = g_slist_next (iter);
1593 modest_account_mgr_free_account_names (account_names);
1594 account_names = NULL;
1598 modest_ui_actions_cancel_send (GtkAction *action, ModestWindow *win)
1601 /* Check if accounts exist */
1602 gboolean accounts_exist =
1603 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1605 /* If not, allow the user to create an account before trying to send/receive. */
1606 if (!accounts_exist)
1607 modest_ui_actions_on_accounts (NULL, win);
1609 /* Cancel all sending operaitons */
1610 modest_ui_actions_cancel_send_all (win);
1614 * Refreshes all accounts. This function will be used by automatic
1618 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1620 GSList *account_names, *iter;
1622 account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1625 iter = account_names;
1627 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1628 iter = g_slist_next (iter);
1631 modest_account_mgr_free_account_names (account_names);
1632 account_names = NULL;
1636 modest_do_refresh_current_folder(ModestWindow *win)
1638 /* Refresh currently selected folder. Note that if we only
1639 want to retreive the headers, then the refresh only will
1640 invoke a poke_status over all folders, i.e., only the
1641 total/unread count will be updated */
1642 if (MODEST_IS_MAIN_WINDOW (win)) {
1643 GtkWidget *header_view, *folder_view;
1644 TnyFolderStore *folder_store;
1646 /* Get folder and header view */
1648 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1649 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1653 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1655 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1657 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1658 MODEST_WIDGET_TYPE_HEADER_VIEW);
1660 /* We do not need to set the contents style
1661 because it hasn't changed. We also do not
1662 need to save the widget status. Just force
1664 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1665 TNY_FOLDER (folder_store),
1666 folder_refreshed_cb,
1667 MODEST_MAIN_WINDOW (win));
1671 g_object_unref (folder_store);
1677 * Handler of the click on Send&Receive button in the main toolbar
1680 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1682 /* Check if accounts exist */
1683 gboolean accounts_exist =
1684 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1686 /* If not, allow the user to create an account before trying to send/receive. */
1687 if (!accounts_exist)
1688 modest_ui_actions_on_accounts (NULL, win);
1690 modest_do_refresh_current_folder (win);
1692 /* Refresh the active account */
1693 modest_ui_actions_do_send_receive (NULL, win);
1698 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1701 GtkWidget *header_view;
1703 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1705 header_view = modest_main_window_get_child_widget (main_window,
1706 MODEST_WIDGET_TYPE_HEADER_VIEW);
1710 conf = modest_runtime_get_conf ();
1712 /* what is saved/restored is depending on the style; thus; we save with
1713 * old style, then update the style, and restore for this new style
1715 modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1717 if (modest_header_view_get_style
1718 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1719 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1720 MODEST_HEADER_VIEW_STYLE_TWOLINES);
1722 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1723 MODEST_HEADER_VIEW_STYLE_DETAILS);
1725 modest_widget_memory_restore (conf, G_OBJECT(header_view),
1726 MODEST_CONF_HEADER_VIEW_KEY);
1731 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
1733 ModestMainWindow *main_window)
1735 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1736 g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1738 /* in the case the folder is empty, show the empty folder message and focus
1740 if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1741 if (modest_header_view_is_empty (header_view)) {
1742 TnyFolder *folder = modest_header_view_get_folder (header_view);
1743 GtkWidget *folder_view =
1744 modest_main_window_get_child_widget (main_window,
1745 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1747 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1748 gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1752 /* If no header has been selected then exit */
1757 if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1758 gtk_widget_grab_focus (GTK_WIDGET(header_view));
1760 /* Update toolbar dimming state */
1761 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1765 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1767 ModestMainWindow *main_window)
1771 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1777 /* headers = tny_simple_list_new (); */
1778 /* tny_list_prepend (headers, G_OBJECT (header)); */
1779 headers = modest_header_view_get_selected_headers (header_view);
1781 _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1783 g_object_unref (headers);
1787 set_active_account_from_tny_account (TnyAccount *account,
1788 ModestWindow *window)
1790 const gchar *server_acc_name = tny_account_get_id (account);
1792 /* We need the TnyAccount provided by the
1793 account store because that is the one that
1794 knows the name of the Modest account */
1795 TnyAccount *modest_server_account = modest_server_account =
1796 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1797 MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
1800 const gchar *modest_acc_name =
1801 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1802 modest_window_set_active_account (window, modest_acc_name);
1803 g_object_unref (modest_server_account);
1808 folder_refreshed_cb (ModestMailOperation *mail_op,
1812 ModestMainWindow *win = NULL;
1813 GtkWidget *header_view;
1814 TnyFolder *current_folder;
1815 gboolean folder_empty = FALSE;
1816 gboolean all_marked_as_deleted = FALSE;
1818 g_return_if_fail (TNY_IS_FOLDER (folder));
1820 win = MODEST_MAIN_WINDOW (user_data);
1822 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1825 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1826 if (current_folder != NULL && folder != current_folder) {
1831 /* Check if folder is empty and set headers view contents style */
1832 folder_empty = (tny_folder_get_all_count (folder) == 0);
1833 all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1834 folder_empty = folder_empty || all_marked_as_deleted ;
1837 printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1838 modest_main_window_set_contents_style (win,
1839 MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1841 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1846 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1847 TnyFolderStore *folder_store,
1849 ModestMainWindow *main_window)
1852 GtkWidget *header_view;
1854 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1856 header_view = modest_main_window_get_child_widget(main_window,
1857 MODEST_WIDGET_TYPE_HEADER_VIEW);
1861 conf = modest_runtime_get_conf ();
1863 if (TNY_IS_ACCOUNT (folder_store)) {
1865 /* Update active account */
1866 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1867 /* Show account details */
1868 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1871 if (TNY_IS_FOLDER (folder_store) && selected) {
1873 /* Update the active account */
1874 TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1876 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1877 g_object_unref (account);
1881 /* Set the header style by default, it could
1882 be changed later by the refresh callback to
1884 modest_main_window_set_contents_style (main_window,
1885 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1887 /* Set folder on header view. This function
1888 will call tny_folder_refresh_async so we
1889 pass a callback that will be called when
1890 finished. We use that callback to set the
1891 empty view if there are no messages */
1892 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1893 TNY_FOLDER (folder_store),
1894 folder_refreshed_cb,
1897 /* Restore configuration. We need to do this
1898 *after* the set_folder because the widget
1899 memory asks the header view about its
1901 modest_widget_memory_restore (modest_runtime_get_conf (),
1902 G_OBJECT(header_view),
1903 MODEST_CONF_HEADER_VIEW_KEY);
1905 /* Update the active account */
1906 modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1907 /* Save only if we're seeing headers */
1908 if (modest_main_window_get_contents_style (main_window) ==
1909 MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1910 modest_widget_memory_save (conf, G_OBJECT (header_view),
1911 MODEST_CONF_HEADER_VIEW_KEY);
1912 modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1916 /* Update toolbar dimming state */
1917 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1921 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1928 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1930 online = tny_device_is_online (modest_runtime_get_device());
1933 /* already online -- the item is simply not there... */
1934 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1936 GTK_MESSAGE_WARNING,
1938 _("The %s you selected cannot be found"),
1940 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
1941 gtk_dialog_run (GTK_DIALOG(dialog));
1943 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1946 _("mcen_bd_dialog_cancel"),
1947 GTK_RESPONSE_REJECT,
1948 _("mcen_bd_dialog_ok"),
1949 GTK_RESPONSE_ACCEPT,
1951 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1952 "Do you want to get online?"), item);
1953 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1954 gtk_label_new (txt), FALSE, FALSE, 0);
1955 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1958 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1959 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1960 /* TODO: Comment about why is this commented out: */
1961 /* modest_platform_connect_and_wait (); */
1964 gtk_widget_destroy (dialog);
1968 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1971 /* g_message ("%s %s", __FUNCTION__, link); */
1976 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1979 modest_platform_activate_uri (link);
1983 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1986 modest_platform_show_uri_popup (link);
1990 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1993 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1997 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1998 const gchar *address,
2001 /* g_message ("%s %s", __FUNCTION__, address); */
2005 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2007 TnyTransportAccount *transport_account;
2008 ModestMailOperation *mail_operation;
2010 gchar *account_name, *from;
2011 ModestAccountMgr *account_mgr;
2012 gchar *info_text = NULL;
2014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2016 data = modest_msg_edit_window_get_msg_data (edit_window);
2018 account_mgr = modest_runtime_get_account_mgr();
2019 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2021 account_name = modest_account_mgr_get_default_account (account_mgr);
2022 if (!account_name) {
2023 g_printerr ("modest: no account found\n");
2024 modest_msg_edit_window_free_msg_data (edit_window, data);
2028 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2029 account_name = g_strdup (data->account_name);
2033 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2034 (modest_runtime_get_account_store(),
2036 TNY_ACCOUNT_TYPE_TRANSPORT));
2037 if (!transport_account) {
2038 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2039 g_free (account_name);
2040 modest_msg_edit_window_free_msg_data (edit_window, data);
2043 from = modest_account_mgr_get_from_string (account_mgr, account_name);
2045 /* Create the mail operation */
2046 mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2047 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2049 modest_mail_operation_save_to_drafts (mail_operation,
2061 data->priority_flags);
2064 g_free (account_name);
2065 g_object_unref (G_OBJECT (transport_account));
2066 g_object_unref (G_OBJECT (mail_operation));
2068 modest_msg_edit_window_free_msg_data (edit_window, data);
2070 info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2071 modest_platform_information_banner (NULL, NULL, info_text);
2075 /* For instance, when clicking the Send toolbar button when editing a message: */
2077 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2081 if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2084 /* Offer the connection dialog, if necessary: */
2085 if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2088 /* FIXME: Code added just for testing. The final version will
2089 use the send queue provided by tinymail and some
2091 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2092 gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2094 account_name = modest_account_mgr_get_default_account (account_mgr);
2096 if (!account_name) {
2097 /* Run account setup wizard */
2098 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2103 MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2105 if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2106 account_name = g_strdup (data->account_name);
2109 /* Get the currently-active transport account for this modest account: */
2110 TnyTransportAccount *transport_account =
2111 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2112 (modest_runtime_get_account_store(),
2114 if (!transport_account) {
2115 /* Run account setup wizard */
2116 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2121 gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2123 /* modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent")); */
2125 /* Create the mail operation */
2126 ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2127 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2129 modest_mail_operation_send_new_mail (mail_operation,
2140 data->priority_flags);
2144 g_free (account_name);
2145 g_object_unref (G_OBJECT (transport_account));
2146 g_object_unref (G_OBJECT (mail_operation));
2148 modest_msg_edit_window_free_msg_data (edit_window, data);
2149 modest_msg_edit_window_set_sent (edit_window, TRUE);
2151 /* Save settings and close the window: */
2152 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2156 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2157 ModestMsgEditWindow *window)
2159 ModestMsgEditFormatState *format_state = NULL;
2161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2162 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2164 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2167 format_state = modest_msg_edit_window_get_format_state (window);
2168 g_return_if_fail (format_state != NULL);
2170 format_state->bold = gtk_toggle_action_get_active (action);
2171 modest_msg_edit_window_set_format_state (window, format_state);
2172 g_free (format_state);
2177 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2178 ModestMsgEditWindow *window)
2180 ModestMsgEditFormatState *format_state = NULL;
2182 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2183 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2185 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2188 format_state = modest_msg_edit_window_get_format_state (window);
2189 g_return_if_fail (format_state != NULL);
2191 format_state->italics = gtk_toggle_action_get_active (action);
2192 modest_msg_edit_window_set_format_state (window, format_state);
2193 g_free (format_state);
2198 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2199 ModestMsgEditWindow *window)
2201 ModestMsgEditFormatState *format_state = NULL;
2203 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2204 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2206 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2209 format_state = modest_msg_edit_window_get_format_state (window);
2210 g_return_if_fail (format_state != NULL);
2212 format_state->bullet = gtk_toggle_action_get_active (action);
2213 modest_msg_edit_window_set_format_state (window, format_state);
2214 g_free (format_state);
2219 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2220 GtkRadioAction *selected,
2221 ModestMsgEditWindow *window)
2223 ModestMsgEditFormatState *format_state = NULL;
2224 GtkJustification value;
2226 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2228 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2231 value = gtk_radio_action_get_current_value (selected);
2233 format_state = modest_msg_edit_window_get_format_state (window);
2234 g_return_if_fail (format_state != NULL);
2236 format_state->justification = value;
2237 modest_msg_edit_window_set_format_state (window, format_state);
2238 g_free (format_state);
2242 modest_ui_actions_on_select_editor_color (GtkAction *action,
2243 ModestMsgEditWindow *window)
2245 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2246 g_return_if_fail (GTK_IS_ACTION (action));
2248 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2251 modest_msg_edit_window_select_color (window);
2255 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2256 ModestMsgEditWindow *window)
2258 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2259 g_return_if_fail (GTK_IS_ACTION (action));
2261 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2264 modest_msg_edit_window_select_background_color (window);
2268 modest_ui_actions_on_insert_image (GtkAction *action,
2269 ModestMsgEditWindow *window)
2271 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2272 g_return_if_fail (GTK_IS_ACTION (action));
2274 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2277 modest_msg_edit_window_insert_image (window);
2281 modest_ui_actions_on_attach_file (GtkAction *action,
2282 ModestMsgEditWindow *window)
2284 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2285 g_return_if_fail (GTK_IS_ACTION (action));
2287 modest_msg_edit_window_offer_attach_file (window);
2291 modest_ui_actions_on_remove_attachments (GtkAction *action,
2292 ModestMsgEditWindow *window)
2294 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2295 g_return_if_fail (GTK_IS_ACTION (action));
2297 modest_msg_edit_window_remove_attachments (window, NULL);
2301 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2304 ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2305 const GError *error = modest_mail_operation_get_error (mail_op);
2309 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2310 modest_mail_operation_get_error (mail_op)->message);
2315 modest_ui_actions_create_folder(GtkWidget *parent_window,
2316 GtkWidget *folder_view)
2318 TnyFolderStore *parent_folder;
2320 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2322 if (parent_folder) {
2323 gboolean finished = FALSE;
2325 gchar *folder_name = NULL, *suggested_name = NULL;
2326 const gchar *proto_str = NULL;
2327 TnyAccount *account;
2329 if (TNY_IS_ACCOUNT (parent_folder))
2330 account = g_object_ref (parent_folder);
2332 account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2333 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2335 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2336 MODEST_PROTOCOL_STORE_POP) {
2338 hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2340 g_object_unref (account);
2342 /* Run the new folder dialog */
2344 result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2349 g_free (suggested_name);
2350 suggested_name = NULL;
2352 if (result == GTK_RESPONSE_REJECT) {
2355 ModestMailOperation *mail_op;
2356 TnyFolder *new_folder = NULL;
2358 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2359 G_OBJECT(parent_window),
2360 modest_ui_actions_new_folder_error_handler,
2363 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2365 new_folder = modest_mail_operation_create_folder (mail_op,
2367 (const gchar *) folder_name);
2369 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2372 g_object_unref (new_folder);
2375 g_object_unref (mail_op);
2378 suggested_name = folder_name;
2382 g_object_unref (parent_folder);
2387 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2389 GtkWidget *folder_view;
2391 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2393 folder_view = modest_main_window_get_child_widget (main_window,
2394 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2398 modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2402 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2405 ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2406 const GError *error = NULL;
2407 const gchar *message = NULL;
2409 /* Get error message */
2410 error = modest_mail_operation_get_error (mail_op);
2412 g_return_if_reached ();
2414 switch (error->code) {
2415 case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2416 message = _CS("ckdg_ib_folder_already_exists");
2419 g_return_if_reached ();
2422 modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2426 modest_ui_actions_on_rename_folder (GtkAction *action,
2427 ModestMainWindow *main_window)
2429 TnyFolderStore *folder;
2430 GtkWidget *folder_view;
2431 GtkWidget *header_view;
2433 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2435 folder_view = modest_main_window_get_child_widget (main_window,
2436 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2440 header_view = modest_main_window_get_child_widget (main_window,
2441 MODEST_WIDGET_TYPE_HEADER_VIEW);
2446 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2450 /* Offer the connection dialog if necessary: */
2451 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2452 g_object_unref (G_OBJECT (folder));
2457 if (TNY_IS_FOLDER (folder)) {
2460 const gchar *current_name;
2461 TnyFolderStore *parent;
2463 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2464 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2465 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window),
2466 parent, current_name,
2468 g_object_unref (parent);
2470 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2471 ModestMailOperation *mail_op;
2472 GtkTreeSelection *sel = NULL;
2475 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2476 G_OBJECT(main_window),
2477 modest_ui_actions_rename_folder_error_handler,
2481 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2484 /* Clear the headers view */
2485 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2486 gtk_tree_selection_unselect_all (sel);
2488 /* Select *after* the changes */
2489 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2490 TNY_FOLDER(folder), TRUE);
2492 modest_mail_operation_rename_folder (mail_op,
2493 TNY_FOLDER (folder),
2494 (const gchar *) folder_name);
2496 g_object_unref (mail_op);
2497 g_free (folder_name);
2500 g_object_unref (folder);
2504 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2507 GObject *win = modest_mail_operation_get_source (mail_op);
2509 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2510 _("mail_in_ui_folder_delete_error"));
2511 g_object_unref (win);
2515 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2517 TnyFolderStore *folder;
2518 GtkWidget *folder_view;
2522 g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2524 folder_view = modest_main_window_get_child_widget (main_window,
2525 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2529 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2531 /* Show an error if it's an account */
2532 if (!TNY_IS_FOLDER (folder)) {
2533 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2534 _("mail_in_ui_folder_delete_error"));
2535 g_object_unref (G_OBJECT (folder));
2539 /* Offer the connection dialog if necessary: */
2540 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2541 g_object_unref (G_OBJECT (folder));
2546 message = g_strdup_printf (_("mcen_nc_delete_folder_text"),
2547 tny_folder_get_name (TNY_FOLDER (folder)));
2548 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2549 (const gchar *) message);
2552 if (response == GTK_RESPONSE_OK) {
2553 ModestMailOperation *mail_op;
2554 GtkTreeSelection *sel;
2556 /* Unselect the folder before deleting it to free the headers */
2557 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2558 gtk_tree_selection_unselect_all (sel);
2560 /* Create the mail operation */
2562 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE,
2563 G_OBJECT(main_window),
2564 modest_ui_actions_delete_folder_error_handler,
2567 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2569 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2570 g_object_unref (G_OBJECT (mail_op));
2573 g_object_unref (G_OBJECT (folder));
2577 modest_ui_actions_on_delete_folder (GtkAction *action,
2578 ModestMainWindow *main_window)
2580 GtkWidget *folder_view;
2581 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2583 delete_folder (main_window, FALSE);
2584 folder_view = modest_main_window_get_child_widget (main_window,
2585 MODEST_WIDGET_TYPE_FOLDER_VIEW);
2588 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2592 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2594 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2596 delete_folder (main_window, TRUE);
2601 show_error (GtkWidget *parent_widget, const gchar* text)
2603 hildon_banner_show_information(parent_widget, NULL, text);
2606 GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2608 GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2615 gtk_dialog_run (dialog);
2616 gtk_widget_destroy (GTK_WIDGET (dialog));
2621 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
2622 const gchar* server_account_name,
2627 ModestMainWindow *main_window)
2629 g_return_if_fail(server_account_name);
2630 /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2632 /* Initalize output parameters: */
2639 #ifdef MODEST_PLATFORM_MAEMO
2640 /* Maemo uses a different (awkward) button order,
2641 * It should probably just use gtk_alternative_dialog_button_order ().
2643 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2646 _("mcen_bd_dialog_ok"),
2647 GTK_RESPONSE_ACCEPT,
2648 _("mcen_bd_dialog_cancel"),
2649 GTK_RESPONSE_REJECT,
2652 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2656 GTK_RESPONSE_REJECT,
2658 GTK_RESPONSE_ACCEPT,
2660 #endif /* MODEST_PLATFORM_MAEMO */
2662 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2664 gchar *server_name = modest_server_account_get_hostname (
2665 modest_runtime_get_account_mgr(), server_account_name);
2666 if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2667 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2672 /* This causes a warning because the logical ID has no %s in it,
2673 * though the translation does, but there is not much we can do about that: */
2674 gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2675 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2678 g_free (server_name);
2682 gchar *initial_username = modest_server_account_get_username (
2683 modest_runtime_get_account_mgr(), server_account_name);
2685 GtkWidget *entry_username = gtk_entry_new ();
2686 if (initial_username)
2687 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2688 /* Dim this if a connection has ever succeeded with this username,
2689 * as per the UI spec: */
2690 const gboolean username_known =
2691 modest_server_account_get_username_has_succeeded(
2692 modest_runtime_get_account_mgr(), server_account_name);
2693 gtk_widget_set_sensitive (entry_username, !username_known);
2695 #ifdef MODEST_PLATFORM_MAEMO
2696 /* Auto-capitalization is the default, so let's turn it off: */
2697 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2699 /* Create a size group to be used by all captions.
2700 * Note that HildonCaption does not create a default size group if we do not specify one.
2701 * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2702 GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2704 GtkWidget *caption = hildon_caption_new (sizegroup,
2705 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2706 gtk_widget_show (entry_username);
2707 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
2708 FALSE, FALSE, MODEST_MARGIN_HALF);
2709 gtk_widget_show (caption);
2711 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2713 #endif /* MODEST_PLATFORM_MAEMO */
2716 GtkWidget *entry_password = gtk_entry_new ();
2717 gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2718 /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2720 #ifdef MODEST_PLATFORM_MAEMO
2721 /* Auto-capitalization is the default, so let's turn it off: */
2722 hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
2723 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2725 caption = hildon_caption_new (sizegroup,
2726 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2727 gtk_widget_show (entry_password);
2728 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
2729 FALSE, FALSE, MODEST_MARGIN_HALF);
2730 gtk_widget_show (caption);
2731 g_object_unref (sizegroup);
2733 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2735 #endif /* MODEST_PLATFORM_MAEMO */
2737 /* This is not in the Maemo UI spec:
2738 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2739 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2743 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2745 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2747 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2749 modest_server_account_set_username (
2750 modest_runtime_get_account_mgr(), server_account_name,
2753 const gboolean username_was_changed =
2754 (strcmp (*username, initial_username) != 0);
2755 if (username_was_changed) {
2756 g_warning ("%s: tinymail does not yet support changing the "
2757 "username in the get_password() callback.\n", __FUNCTION__);
2762 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2764 /* We do not save the password in the configuration,
2765 * because this function is only called for passwords that should
2766 * not be remembered:
2767 modest_server_account_set_password (
2768 modest_runtime_get_account_mgr(), server_account_name,
2777 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2789 /* This is not in the Maemo UI spec:
2790 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2796 gtk_widget_destroy (dialog);
2798 /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2802 modest_ui_actions_on_cut (GtkAction *action,
2803 ModestWindow *window)
2805 GtkWidget *focused_widget;
2806 GtkClipboard *clipboard;
2808 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2809 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2810 if (GTK_IS_EDITABLE (focused_widget)) {
2811 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2812 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2813 gtk_clipboard_store (clipboard);
2814 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2815 GtkTextBuffer *buffer;
2817 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2818 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2819 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2820 gtk_clipboard_store (clipboard);
2821 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2822 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2823 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2824 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2829 modest_ui_actions_on_copy (GtkAction *action,
2830 ModestWindow *window)
2832 GtkClipboard *clipboard;
2833 GtkWidget *focused_widget;
2835 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2836 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2838 if (GTK_IS_LABEL (focused_widget)) {
2839 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2840 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2841 gtk_clipboard_store (clipboard);
2842 } else if (GTK_IS_EDITABLE (focused_widget)) {
2843 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2844 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2845 gtk_clipboard_store (clipboard);
2846 } else if (GTK_IS_HTML (focused_widget)) {
2847 gtk_html_copy (GTK_HTML (focused_widget));
2848 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2849 gtk_clipboard_store (clipboard);
2850 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2851 GtkTextBuffer *buffer;
2852 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2853 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2854 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2855 gtk_clipboard_store (clipboard);
2856 } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2857 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2858 TnyIterator *iter = tny_list_create_iterator (header_list);
2859 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2861 gboolean ask = FALSE;
2863 TnyFolder *folder = tny_header_get_folder (header);
2864 TnyAccount *account = tny_folder_get_account (folder);
2865 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2866 /* If it's POP then ask */
2867 ask = (modest_protocol_info_get_transport_store_protocol (proto_str) ==
2868 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2869 g_object_unref (account);
2870 g_object_unref (folder);
2871 g_object_unref (header);
2874 g_object_unref (iter);
2876 /* Check that the messages have been previously downloaded */
2877 gboolean continue_download = TRUE;
2879 continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2880 if (continue_download)
2881 modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2882 g_object_unref (header_list);
2883 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2884 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2887 /* Show information banner */
2888 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2893 modest_ui_actions_on_undo (GtkAction *action,
2894 ModestWindow *window)
2896 ModestEmailClipboard *clipboard = NULL;
2898 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2899 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2900 } else if (MODEST_IS_MAIN_WINDOW (window)) {
2901 /* Clear clipboard source */
2902 clipboard = modest_runtime_get_email_clipboard ();
2903 modest_email_clipboard_clear (clipboard);
2906 g_return_if_reached ();
2911 modest_ui_actions_on_redo (GtkAction *action,
2912 ModestWindow *window)
2914 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2915 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2918 g_return_if_reached ();
2924 paste_msgs_cb (const GObject *object, gpointer user_data)
2926 g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2927 g_return_if_fail (GTK_IS_WIDGET (user_data));
2929 /* destroy information note */
2930 gtk_widget_destroy (GTK_WIDGET(user_data));
2934 paste_as_attachment_free (gpointer data)
2936 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2938 gtk_widget_destroy (helper->banner);
2939 g_object_unref (helper->banner);
2944 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2949 PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2950 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2955 modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2960 modest_ui_actions_on_paste (GtkAction *action,
2961 ModestWindow *window)
2963 GtkWidget *focused_widget = NULL;
2964 GtkWidget *inf_note = NULL;
2965 ModestMailOperation *mail_op = NULL;
2967 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2968 if (GTK_IS_EDITABLE (focused_widget)) {
2969 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2970 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2971 ModestEmailClipboard *e_clipboard = NULL;
2972 e_clipboard = modest_runtime_get_email_clipboard ();
2973 if (modest_email_clipboard_cleared (e_clipboard)) {
2974 GtkTextBuffer *buffer;
2975 GtkClipboard *clipboard;
2977 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2978 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2979 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2980 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2981 ModestMailOperation *mail_op;
2982 TnyFolder *src_folder;
2985 PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2986 helper->window = MODEST_MSG_EDIT_WINDOW (window);
2987 helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2988 _CS("ckct_nw_pasting"));
2989 modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2990 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
2992 if (helper->banner != NULL) {
2993 g_object_ref (G_OBJECT (helper->banner));
2994 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2995 gtk_widget_show (GTK_WIDGET (helper->banner));
2999 modest_mail_operation_get_msgs_full (mail_op,
3001 (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3003 paste_as_attachment_free);
3006 } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3007 ModestEmailClipboard *clipboard = NULL;
3008 TnyFolder *src_folder = NULL;
3009 TnyFolderStore *folder_store = NULL;
3010 TnyList *data = NULL;
3011 gboolean delete = FALSE;
3013 /* Check clipboard source */
3014 clipboard = modest_runtime_get_email_clipboard ();
3015 if (modest_email_clipboard_cleared (clipboard))
3018 /* Get elements to paste */
3019 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3021 /* Create a new mail operation */
3022 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3024 /* Get destination folder */
3025 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3027 /* transfer messages */
3031 /* Ask for user confirmation */
3032 response = msgs_move_to_confirmation (GTK_WINDOW (window),
3033 TNY_FOLDER (folder_store),
3037 if (response == GTK_RESPONSE_OK) {
3038 /* Launch notification */
3039 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3040 _CS("ckct_nw_pasting"));
3041 if (inf_note != NULL) {
3042 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3043 gtk_widget_show (GTK_WIDGET(inf_note));
3046 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3047 modest_mail_operation_xfer_msgs (mail_op,
3049 TNY_FOLDER (folder_store),
3054 g_object_unref (mail_op);
3057 } else if (src_folder != NULL) {
3058 /* Launch notification */
3059 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3060 _CS("ckct_nw_pasting"));
3061 if (inf_note != NULL) {
3062 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3063 gtk_widget_show (GTK_WIDGET(inf_note));
3066 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3067 modest_mail_operation_xfer_folder (mail_op,
3077 g_object_unref (data);
3078 if (src_folder != NULL)
3079 g_object_unref (src_folder);
3080 if (folder_store != NULL)
3081 g_object_unref (folder_store);
3087 modest_ui_actions_on_select_all (GtkAction *action,
3088 ModestWindow *window)
3090 GtkWidget *focused_widget;
3092 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3093 if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3094 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3095 } else if (GTK_IS_LABEL (focused_widget)) {
3096 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3097 } else if (GTK_IS_EDITABLE (focused_widget)) {
3098 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3099 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3100 GtkTextBuffer *buffer;
3101 GtkTextIter start, end;
3103 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3104 gtk_text_buffer_get_start_iter (buffer, &start);
3105 gtk_text_buffer_get_end_iter (buffer, &end);
3106 gtk_text_buffer_select_range (buffer, &start, &end);
3107 } else if (GTK_IS_HTML (focused_widget)) {
3108 gtk_html_select_all (GTK_HTML (focused_widget));
3109 } else if (MODEST_IS_MAIN_WINDOW (window)) {
3110 GtkWidget *header_view = focused_widget;
3111 GtkTreeSelection *selection = NULL;
3113 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
3114 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3115 MODEST_WIDGET_TYPE_HEADER_VIEW);
3117 /* Select all messages */
3118 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3119 gtk_tree_selection_select_all (selection);
3121 /* Set focuse on header view */
3122 gtk_widget_grab_focus (header_view);
3128 modest_ui_actions_on_mark_as_read (GtkAction *action,
3129 ModestWindow *window)
3131 g_return_if_fail (MODEST_IS_WINDOW(window));
3133 /* Mark each header as read */
3134 do_headers_action (window, headers_action_mark_as_read, NULL);
3138 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3139 ModestWindow *window)
3141 g_return_if_fail (MODEST_IS_WINDOW(window));
3143 /* Mark each header as read */
3144 do_headers_action (window, headers_action_mark_as_unread, NULL);
3148 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3149 GtkRadioAction *selected,
3150 ModestWindow *window)
3154 value = gtk_radio_action_get_current_value (selected);
3155 if (MODEST_IS_WINDOW (window)) {
3156 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3160 void modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3161 GtkRadioAction *selected,
3162 ModestWindow *window)
3164 TnyHeaderFlags flags;
3165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3167 flags = gtk_radio_action_get_current_value (selected);
3168 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3171 void modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3172 GtkRadioAction *selected,
3173 ModestWindow *window)
3177 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3179 file_format = gtk_radio_action_get_current_value (selected);
3180 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3185 modest_ui_actions_on_zoom_plus (GtkAction *action,
3186 ModestWindow *window)
3188 g_return_if_fail (MODEST_IS_WINDOW (window));
3190 modest_window_zoom_plus (MODEST_WINDOW (window));
3194 modest_ui_actions_on_zoom_minus (GtkAction *action,
3195 ModestWindow *window)
3197 g_return_if_fail (MODEST_IS_WINDOW (window));
3199 modest_window_zoom_minus (MODEST_WINDOW (window));
3203 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
3204 ModestWindow *window)
3206 ModestWindowMgr *mgr;
3207 gboolean fullscreen, active;
3208 g_return_if_fail (MODEST_IS_WINDOW (window));
3210 mgr = modest_runtime_get_window_mgr ();
3212 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3213 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3215 if (active != fullscreen) {
3216 modest_window_mgr_set_fullscreen_mode (mgr, active);
3217 gtk_window_present (GTK_WINDOW (window));
3222 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3223 ModestWindow *window)
3225 ModestWindowMgr *mgr;
3226 gboolean fullscreen;
3228 g_return_if_fail (MODEST_IS_WINDOW (window));
3230 mgr = modest_runtime_get_window_mgr ();
3231 fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3232 modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3234 gtk_window_present (GTK_WINDOW (window));
3238 * Used by modest_ui_actions_on_details to call do_headers_action
3241 headers_action_show_details (TnyHeader *header,
3242 ModestWindow *window,
3249 dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3252 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3253 gtk_widget_show_all (dialog);
3254 gtk_dialog_run (GTK_DIALOG (dialog));
3256 gtk_widget_destroy (dialog);
3260 * Show the folder details in a ModestDetailsDialog widget
3263 show_folder_details (TnyFolder *folder,
3269 dialog = modest_details_dialog_new_with_folder (window, folder);
3272 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3273 gtk_widget_show_all (dialog);
3274 gtk_dialog_run (GTK_DIALOG (dialog));
3276 gtk_widget_destroy (dialog);
3280 * Show the header details in a ModestDetailsDialog widget
3283 modest_ui_actions_on_details (GtkAction *action,
3286 TnyList * headers_list;
3290 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3293 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3296 g_object_unref (msg);
3298 headers_list = get_selected_headers (win);
3302 iter = tny_list_create_iterator (headers_list);
3304 header = TNY_HEADER (tny_iterator_get_current (iter));
3306 headers_action_show_details (header, win, NULL);
3307 g_object_unref (header);
3310 g_object_unref (iter);
3311 g_object_unref (headers_list);
3313 } else if (MODEST_IS_MAIN_WINDOW (win)) {
3314 GtkWidget *folder_view, *header_view;
3316 /* Check which widget has the focus */
3317 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3318 MODEST_WIDGET_TYPE_FOLDER_VIEW);
3319 if (gtk_widget_is_focus (folder_view)) {
3320 TnyFolderStore *folder_store
3321 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3322 if (!folder_store) {
3323 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3326 /* Show only when it's a folder */
3327 /* This function should not be called for account items,
3328 * because we dim the menu item for them. */
3329 if (TNY_IS_FOLDER (folder_store)) {
3330 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3333 g_object_unref (folder_store);
3336 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3337 MODEST_WIDGET_TYPE_HEADER_VIEW);
3338 /* Show details of each header */
3339 do_headers_action (win, headers_action_show_details, header_view);
3345 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3346 ModestMsgEditWindow *window)
3348 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3350 modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3354 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3355 ModestMsgEditWindow *window)
3357 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3359 modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3363 modest_ui_actions_toggle_folders_view (GtkAction *action,
3364 ModestMainWindow *main_window)
3366 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3368 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3369 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3371 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3375 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
3376 ModestWindow *window)
3378 gboolean active, fullscreen = FALSE;
3379 ModestWindowMgr *mgr;
3381 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3383 /* Check if we want to toggle the toolbar vuew in fullscreen
3385 if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
3386 "ViewShowToolbarFullScreen")) {
3390 /* Toggle toolbar */
3391 mgr = modest_runtime_get_window_mgr ();
3392 modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3396 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3397 ModestMsgEditWindow *window)
3399 modest_msg_edit_window_select_font (window);
3403 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3404 const gchar *display_name,
3407 /* Do not change the application name if the widget has not
3408 the focus. This callback could be called even if the folder
3409 view has not the focus, because the handled signal could be
3410 emitted when the folder view is redrawn */
3411 if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3413 gtk_window_set_title (window, display_name);
3415 gtk_window_set_title (window, " ");
3420 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3422 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3423 modest_msg_edit_window_select_contacts (window);
3427 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3429 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3430 modest_msg_edit_window_check_names (window, FALSE);
3434 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3436 modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3437 GTK_WIDGET (user_data));
3441 create_move_to_dialog (GtkWindow *win,
3442 GtkWidget *folder_view,
3443 GtkWidget **tree_view)
3445 GtkWidget *dialog, *scroll;
3446 GtkWidget *new_button;
3448 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3450 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3453 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3454 /* We do this manually so GTK+ does not associate a response ID for
3456 new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3457 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3458 gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3460 /* Create scrolled window */
3461 scroll = gtk_scrolled_window_new (NULL, NULL);
3462 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
3463 GTK_POLICY_AUTOMATIC,
3464 GTK_POLICY_AUTOMATIC);
3466 /* Create folder view */
3467 *tree_view = modest_platform_create_folder_view (NULL);
3469 g_signal_connect (G_OBJECT (new_button),
3471 G_CALLBACK(create_move_to_dialog_on_new_folder),
3474 /* It could happen that we're trying to move a message from a
3475 window (msg window for example) after the main window was
3476 closed, so we can not just get the model of the folder
3478 if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3479 const gchar *visible_id = NULL;
3481 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
3482 MODEST_FOLDER_VIEW(*tree_view));
3485 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3487 /* Show the same account than the one that is shown in the main window */
3488 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view),
3491 const gchar *active_account_name = NULL;
3492 ModestAccountMgr *mgr = NULL;
3493 ModestAccountData *acc_data = NULL;
3495 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view),
3496 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3498 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3499 mgr = modest_runtime_get_account_mgr ();
3500 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3502 /* Set the new visible & active account */
3503 if (acc_data && acc_data->store_account) {
3504 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3505 acc_data->store_account->account_name);
3506 modest_account_mgr_free_account_data (mgr, acc_data);
3510 /* Hide special folders */
3511 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3513 gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3515 /* Add scroll to dialog */
3516 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
3517 scroll, TRUE, TRUE, 0);
3519 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3520 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3526 * Returns TRUE if at least one of the headers of the list belongs to
3527 * a message that has been fully retrieved.
3529 #if 0 /* no longer in use. delete in 2007.10 */
3531 has_retrieved_msgs (TnyList *list)
3534 gboolean found = FALSE;
3536 iter = tny_list_create_iterator (list);
3537 while (!tny_iterator_is_done (iter) && !found) {
3539 TnyHeaderFlags flags = 0;
3541 header = TNY_HEADER (tny_iterator_get_current (iter));
3543 flags = tny_header_get_flags (header);
3544 if (flags & TNY_HEADER_FLAG_CACHED)
3545 /* if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3548 g_object_unref (header);
3552 tny_iterator_next (iter);
3554 g_object_unref (iter);
3562 * Shows a confirmation dialog to the user when we're moving messages
3563 * from a remote server to the local storage. Returns the dialog
3564 * response. If it's other kind of movement the it always returns
3568 msgs_move_to_confirmation (GtkWindow *win,
3569 TnyFolder *dest_folder,
3573 gint response = GTK_RESPONSE_OK;
3575 /* If the destination is a local folder (or MMC folder )*/
3576 if (!modest_tny_folder_is_remote_folder (dest_folder)) {
3581 TnyFolder *src_folder = NULL;
3582 TnyIterator *iter = NULL;
3583 TnyHeader *header = NULL;
3585 /* get the device */
3587 device = modest_runtime_get_device ();
3589 is_online = tny_device_is_online (device);
3591 g_warning ("failed to get tny device"); /* should not happend */
3595 /* Get source folder */
3596 iter = tny_list_create_iterator (headers);
3597 header = TNY_HEADER (tny_iterator_get_current (iter));
3599 src_folder = tny_header_get_folder (header);
3600 g_object_unref (header);
3603 g_object_unref (iter);
3605 /* if no src_folder, message may be an attahcment */
3606 if (src_folder == NULL)
3607 return GTK_RESPONSE_CANCEL;
3609 /* If the source is a remote folder */
3610 if (!is_online && modest_tny_folder_is_remote_folder (src_folder)) {
3612 const gchar *message = NULL;
3613 message = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs",
3614 tny_list_get_length (headers));
3615 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3616 (const gchar *) message);
3618 response = GTK_RESPONSE_OK;
3620 g_object_unref (src_folder);
3629 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3631 ModestMsgViewWindow *self = NULL;
3633 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3634 self = MODEST_MSG_VIEW_WINDOW (object);
3636 if (!modest_msg_view_window_select_next_message (self))
3637 if (!modest_msg_view_window_select_previous_message (self))
3638 /* No more messages to view, so close this window */
3639 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3643 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
3646 GObject *win = modest_mail_operation_get_source (mail_op);
3647 const GError *error = NULL;
3648 const gchar *message = NULL;
3650 /* Get error message */
3651 error = modest_mail_operation_get_error (mail_op);
3652 if (error != NULL && error->message != NULL) {
3653 message = error->message;
3655 message = _("mail_in_ui_folder_move_target_error");
3658 /* Show notification dialog */
3659 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3660 g_object_unref (win);
3664 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op,
3667 GObject *win = modest_mail_operation_get_source (mail_op);
3668 const GError *error = modest_mail_operation_get_error (mail_op);
3670 g_return_if_fail (error != NULL);
3671 if (error->message != NULL)
3672 g_printerr ("modest: %s\n", error->message);
3674 g_printerr ("modest: unkonw error on send&receive operation");
3676 /* Show error message */
3677 /* if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3678 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3679 /* _CS("sfil_ib_unable_to_receive")); */
3681 /* modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3682 /* _CS("sfil_ib_unable_to_send")); */
3683 g_object_unref (win);
3687 open_msg_for_purge_cb (ModestMailOperation *mail_op,
3694 gint pending_purges = 0;
3695 gboolean some_purged = FALSE;
3696 ModestWindow *win = MODEST_WINDOW (user_data);
3697 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3699 /* If there was any error */
3700 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3701 modest_window_mgr_unregister_header (mgr, header);
3705 /* Once the message has been retrieved for purging, we check if
3706 * it's all ok for purging */
3708 parts = tny_simple_list_new ();
3709 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3710 iter = tny_list_create_iterator (parts);
3712 while (!tny_iterator_is_done (iter)) {
3714 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3715 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3716 if (tny_mime_part_is_purged (part))
3723 g_object_unref (part);
3725 tny_iterator_next (iter);
3728 if (pending_purges>0) {
3730 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3732 if (response == GTK_RESPONSE_OK) {
3733 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3734 tny_iterator_first (iter);
3735 while (!tny_iterator_is_done (iter)) {
3738 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3739 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3740 tny_mime_part_set_purged (part);
3743 g_object_unref (part);
3745 tny_iterator_next (iter);
3748 tny_msg_rewrite_cache (msg);
3751 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3754 /* remove attachments */
3755 tny_iterator_first (iter);
3756 while (!tny_iterator_is_done (iter)) {
3759 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3761 /* One for the reference given by tny_iterator_get_current(): */
3762 g_object_unref (part);
3764 /* TODO: Is this meant to remove the attachment by doing another unref()?
3765 * Otherwise, this seems useless. */
3768 tny_iterator_next (iter);
3770 modest_window_mgr_unregister_header (mgr, header);
3772 g_object_unref (iter);
3773 g_object_unref (parts);
3777 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3778 ModestMainWindow *win)
3780 GtkWidget *header_view;
3781 TnyList *header_list;
3784 TnyHeaderFlags flags;
3785 ModestWindow *msg_view_window = NULL;
3788 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3790 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3791 MODEST_WIDGET_TYPE_HEADER_VIEW);
3793 header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3795 if (tny_list_get_length (header_list) == 1) {
3796 iter = tny_list_create_iterator (header_list);
3797 header = TNY_HEADER (tny_iterator_get_current (iter));
3798 g_object_unref (iter);
3803 found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3804 header, &msg_view_window);
3805 flags = tny_header_get_flags (header);
3806 if (!(flags & TNY_HEADER_FLAG_CACHED))
3809 if (msg_view_window != NULL)
3810 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3812 /* do nothing; uid was registered before, so window is probably on it's way */
3813 g_warning ("debug: header %p has already been registered", header);
3816 ModestMailOperation *mail_op = NULL;
3817 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3818 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3820 modest_ui_actions_get_msgs_full_error_handler,
3822 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3823 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3825 g_object_unref (mail_op);
3828 g_object_unref (header);
3830 g_object_unref (header_list);
3834 * Utility function that transfer messages from both the main window
3835 * and the msg view window when using the "Move to" dialog
3838 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3841 TnyList *headers = NULL;
3843 TnyAccount *dst_account = NULL;
3844 const gchar *proto_str = NULL;
3845 gboolean dst_is_pop = FALSE;
3847 if (!TNY_IS_FOLDER (dst_folder)) {
3848 modest_platform_information_banner (GTK_WIDGET (win),
3850 _CS("ckdg_ib_unable_to_move_to_current_location"));
3854 dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
3855 proto_str = tny_account_get_proto (dst_account);
3857 /* tinymail will return NULL for local folders it seems */
3858 dst_is_pop = proto_str &&
3859 (modest_protocol_info_get_transport_store_protocol (proto_str) ==
3860 MODEST_PROTOCOL_STORE_POP);
3862 g_object_unref (dst_account);
3864 /* Get selected headers */
3865 headers = get_selected_headers (MODEST_WINDOW (win));
3868 modest_platform_information_banner (GTK_WIDGET (win),
3870 ngettext("mail_in_ui_folder_move_target_error",
3871 "mail_in_ui_folder_move_targets_error",
3872 tny_list_get_length (headers)));
3873 g_object_unref (headers);
3877 /* Ask for user confirmation */
3878 response = msgs_move_to_confirmation (GTK_WINDOW (win),
3879 TNY_FOLDER (dst_folder),
3883 /* Transfer messages */
3884 if (response == GTK_RESPONSE_OK) {
3885 ModestMailOperation *mail_op =
3886 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3888 modest_ui_actions_move_folder_error_handler,
3890 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3893 modest_mail_operation_xfer_msgs (mail_op,
3895 TNY_FOLDER (dst_folder),
3897 (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3900 g_object_unref (G_OBJECT (mail_op));
3902 g_object_unref (headers);
3906 * UI handler for the "Move to" action when invoked from the
3910 modest_ui_actions_on_main_window_move_to (GtkAction *action,
3911 GtkWidget *folder_view,
3912 TnyFolderStore *dst_folder,
3913 ModestMainWindow *win)
3915 GtkWidget *header_view = NULL;
3916 ModestMailOperation *mail_op = NULL;
3917 TnyFolderStore *src_folder;
3919 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3921 /* Get the source folder */
3922 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3924 /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3925 if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win),
3929 /* Get header view */
3931 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3933 /* Get folder or messages to transfer */
3934 if (gtk_widget_is_focus (folder_view)) {
3935 GtkTreeSelection *sel;
3937 /* Allow only to transfer folders to the local root folder */
3938 if (TNY_IS_ACCOUNT (dst_folder) &&
3939 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3942 /* Clean folder on header view before moving it */
3943 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3944 gtk_tree_selection_unselect_all (sel);
3946 if (TNY_IS_FOLDER (src_folder)) {
3948 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3950 modest_ui_actions_move_folder_error_handler,
3952 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3955 modest_mail_operation_xfer_folder (mail_op,
3956 TNY_FOLDER (src_folder),
3959 /* Unref mail operation */
3960 g_object_unref (G_OBJECT (mail_op));
3962 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
3964 } else if (gtk_widget_is_focus (header_view)) {
3965 /* Transfer messages */
3966 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3971 g_object_unref (src_folder);
3976 * UI handler for the "Move to" action when invoked from the
3977 * ModestMsgViewWindow
3980 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
3981 TnyFolderStore *dst_folder,
3982 ModestMsgViewWindow *win)
3984 TnyHeader *header = NULL;
3985 TnyFolder *src_folder;
3987 /* Create header list */
3988 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
3989 src_folder = tny_header_get_folder(header);
3990 g_object_unref (header);
3992 /* Transfer the message */
3993 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3994 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3996 g_object_unref (src_folder);
4000 modest_ui_actions_on_move_to (GtkAction *action,
4003 GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4005 TnyFolderStore *dst_folder = NULL;
4006 ModestMainWindow *main_window;
4008 g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4009 MODEST_IS_MSG_VIEW_WINDOW (win));
4011 /* Get the main window if exists */
4012 if (MODEST_IS_MAIN_WINDOW (win))
4013 main_window = MODEST_MAIN_WINDOW (win);
4016 MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4018 /* Get the folder view widget if exists */
4020 folder_view = modest_main_window_get_child_widget (main_window,
4021 MODEST_WIDGET_TYPE_FOLDER_VIEW);
4025 /* Create and run the dialog */
4026 dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4027 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4028 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4029 result = gtk_dialog_run (GTK_DIALOG(dialog));
4030 g_object_ref (tree_view);
4031 gtk_widget_destroy (dialog);
4033 if (result != GTK_RESPONSE_ACCEPT)
4036 dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4037 /* Offer the connection dialog if necessary: */
4038 if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win),
4041 /* Do window specific stuff */
4042 if (MODEST_IS_MAIN_WINDOW (win))
4043 modest_ui_actions_on_main_window_move_to (action,
4046 MODEST_MAIN_WINDOW (win));
4048 modest_ui_actions_on_msg_view_window_move_to (action,
4050 MODEST_MSG_VIEW_WINDOW (win));
4053 g_object_unref (dst_folder);
4057 * Calls #HeadersFunc for each header already selected in the main
4058 * window or the message currently being shown in the msg view window
4061 do_headers_action (ModestWindow *win,
4065 TnyList *headers_list = NULL;
4066 TnyIterator *iter = NULL;
4067 TnyHeader *header = NULL;
4068 TnyFolder *folder = NULL;
4071 headers_list = get_selected_headers (win);
4075 /* Get the folder */
4076 iter = tny_list_create_iterator (headers_list);
4077 header = TNY_HEADER (tny_iterator_get_current (iter));
4079 folder = tny_header_get_folder (header);
4080 g_object_unref (header);
4083 /* Call the function for each header */
4084 while (!tny_iterator_is_done (iter)) {
4085 header = TNY_HEADER (tny_iterator_get_current (iter));
4086 func (header, win, user_data);
4087 g_object_unref (header);
4088 tny_iterator_next (iter);
4091 /* Trick: do a poke status in order to speed up the signaling
4093 tny_folder_poke_status (folder);
4096 g_object_unref (folder);
4097 g_object_unref (iter);
4098 g_object_unref (headers_list);
4102 modest_ui_actions_view_attachment (GtkAction *action,
4103 ModestWindow *window)
4105 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4106 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4108 /* not supported window for this action */
4109 g_return_if_reached ();
4114 modest_ui_actions_save_attachments (GtkAction *action,
4115 ModestWindow *window)
4117 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4118 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4120 /* not supported window for this action */
4121 g_return_if_reached ();
4126 modest_ui_actions_remove_attachments (GtkAction *action,
4127 ModestWindow *window)
4129 if (MODEST_IS_MAIN_WINDOW (window)) {
4130 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4131 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4132 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4134 /* not supported window for this action */
4135 g_return_if_reached ();
4140 modest_ui_actions_on_settings (GtkAction *action,
4145 dialog = modest_platform_get_global_settings_dialog ();
4146 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4147 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4148 gtk_widget_show_all (dialog);
4150 gtk_dialog_run (GTK_DIALOG (dialog));
4152 gtk_widget_destroy (dialog);
4156 modest_ui_actions_on_help (GtkAction *action,
4159 const gchar *help_id = NULL;
4161 if (MODEST_IS_MAIN_WINDOW (win)) {
4162 const gchar *action_name;
4163 action_name = gtk_action_get_name (action);
4165 if (!strcmp (action_name, "FolderViewCSMHelp") ||
4166 !strcmp (action_name, "HeaderViewCSMHelp")) {
4167 GtkWidget *folder_view;
4168 TnyFolderStore *folder_store;
4169 /* Get selected folder */
4170 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4171 MODEST_WIDGET_TYPE_FOLDER_VIEW);
4172 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4174 /* Switch help_id */
4175 if (TNY_IS_FOLDER (folder_store)) {
4176 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4177 case TNY_FOLDER_TYPE_NORMAL:
4178 help_id = "applications_email_managefolders";
4180 case TNY_FOLDER_TYPE_INBOX:
4181 help_id = "applications_email_inbox";
4183 case TNY_FOLDER_TYPE_OUTBOX:
4184 help_id = "applications_email_outbox";
4186 case TNY_FOLDER_TYPE_SENT:
4187 help_id = "applications_email_sent";
4189 case TNY_FOLDER_TYPE_DRAFTS:
4190 help_id = "applications_email_drafts";
4192 case TNY_FOLDER_TYPE_ARCHIVE:
4193 help_id = "applications_email_managefolders";
4196 help_id = "applications_email_managefolders";
4199 help_id = "applications_email_mainview";
4201 g_object_unref (folder_store);
4203 help_id = "applications_email_mainview";
4205 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4206 help_id = "applications_email_viewer";
4207 } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4208 help_id = "applications_email_editor";
4210 modest_platform_show_help (GTK_WINDOW (win), help_id);
4214 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4215 ModestWindow *window)
4217 ModestMailOperation *mail_op;
4221 headers = get_selected_headers (window);
4225 /* Create mail operation */
4226 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4228 modest_ui_actions_get_msgs_full_error_handler,
4230 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4231 modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4234 g_object_unref (headers);
4235 g_object_unref (mail_op);
4239 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4240 ModestWindow *window)
4242 g_return_if_fail (MODEST_IS_WINDOW (window));
4245 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4249 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4250 ModestWindow *window)
4252 g_return_if_fail (MODEST_IS_WINDOW (window));
4255 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4259 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4260 ModestWindow *window)
4262 g_return_if_fail (MODEST_IS_WINDOW (window));
4265 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4269 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4270 ModestWindow *window)
4272 g_return_if_fail (MODEST_IS_WINDOW (window));
4275 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4279 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4280 ModestWindow *window)
4282 g_return_if_fail (MODEST_IS_WINDOW (window));
4285 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4289 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4290 ModestWindow *window)
4292 g_return_if_fail (MODEST_IS_WINDOW (window));
4295 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4299 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4300 ModestWindow *window)
4302 g_return_if_fail (MODEST_IS_WINDOW (window));
4305 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4309 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4310 ModestWindow *window)
4312 g_return_if_fail (MODEST_IS_WINDOW (window));
4315 modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");
4319 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4321 g_return_if_fail (MODEST_IS_WINDOW (window));
4324 modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");
4328 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4330 g_return_if_fail (MODEST_IS_WINDOW (window));
4332 modest_platform_show_search_messages (GTK_WINDOW (window));
4336 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4338 g_return_if_fail (MODEST_IS_WINDOW (win));
4339 modest_platform_show_addressbook (GTK_WINDOW (win));
4344 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4345 ModestWindow *window)
4347 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4349 modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4353 _on_send_receive_progress_changed (ModestMailOperation *mail_op,
4354 ModestMailOperationState *state,
4357 g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4359 /* Set send/receive operation finished */
4360 if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4361 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));