Move modest folder window to widgets
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-error.h>
50 #include <tny-camel-folder.h>
51 #include <tny-camel-imap-folder.h>
52 #include <tny-camel-pop-folder.h>
53 #include <widgets/modest-header-window.h>
54 #include <widgets/modest-folder-window.h>
55 #ifdef MODEST_TOOLKIT_HILDON2
56 #include <modest-accounts-window.h>
57 #include <hildon/hildon-gtk.h>
58 #include <modest-maemo-utils.h>
59 #endif
60 #include "modest-utils.h"
61 #include "widgets/modest-connection-specific-smtp-window.h"
62 #include "widgets/modest-ui-constants.h"
63 #include <widgets/modest-main-window.h>
64 #include <widgets/modest-msg-view-window.h>
65 #include <widgets/modest-account-view-window.h>
66 #include <widgets/modest-details-dialog.h>
67 #include <widgets/modest-attachments-view.h>
68 #include "widgets/modest-folder-view.h"
69 #include "widgets/modest-global-settings-dialog.h"
70 #include "modest-account-mgr-helpers.h"
71 #include "modest-mail-operation.h"
72 #include "modest-text-utils.h"
73 #include <modest-widget-memory.h>
74 #include <tny-error.h>
75 #include <tny-simple-list.h>
76 #include <tny-msg-view.h>
77 #include <tny-device.h>
78 #include <tny-merge-folder.h>
79 #include <widgets/modest-toolkit-utils.h>
80
81 #include <gtkhtml/gtkhtml.h>
82
83 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
84
85 typedef struct _GetMsgAsyncHelper {
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         gchar *mailbox;
105         GtkWidget *parent_window;
106         TnyHeader *header;
107 } ReplyForwardHelper;
108
109 typedef struct _MoveToHelper {
110         GtkTreeRowReference *reference;
111         GtkWidget *banner;
112 } MoveToHelper;
113
114 typedef struct _PasteAsAttachmentHelper {
115         ModestMsgEditWindow *window;
116         GtkWidget *banner;
117 } PasteAsAttachmentHelper;
118
119 typedef struct {
120         TnyList *list;
121         ModestWindow *win;
122 } MoveToInfo;
123
124 /*
125  * The do_headers_action uses this kind of functions to perform some
126  * action to each member of a list of headers
127  */
128 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
129
130 static void     do_headers_action     (ModestWindow *win,
131                                        HeadersFunc func,
132                                        gpointer user_data);
133
134 static void     open_msg_cb            (ModestMailOperation *mail_op,
135                                         TnyHeader *header,
136                                         gboolean canceled,
137                                         TnyMsg *msg,
138                                         GError *err,
139                                         gpointer user_data);
140
141 static void     reply_forward_cb       (ModestMailOperation *mail_op,
142                                         TnyHeader *header,
143                                         gboolean canceled,
144                                         TnyMsg *msg,
145                                         GError *err,
146                                         gpointer user_data);
147
148 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
149
150 #ifndef MODEST_TOOLKIT_HILDON2
151 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
152                                         TnyFolder *folder,
153                                         gpointer user_data);
154
155 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
156                                           gpointer user_data);
157 #endif
158
159 static gint header_list_count_uncached_msgs (TnyList *header_list);
160
161 static gboolean connect_to_get_msg (ModestWindow *win,
162                                     gint num_of_uncached_msgs,
163                                     TnyAccount *account);
164
165 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
166
167 static void     do_create_folder (GtkWindow *window,
168                                   TnyFolderStore *parent_folder,
169                                   const gchar *suggested_name);
170
171 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
172
173 #ifndef MODEST_TOOLKIT_HILDON2
174 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
175                                                       GtkWidget *folder_view,
176                                                       TnyFolderStore *dst_folder,
177                                                       ModestMainWindow *win);
178
179 #else
180 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
181                                                         TnyFolderStore *dst_folder,
182                                                         TnyList *selection,
183                                                         GtkWindow *win);
184 #endif
185
186 static void modest_ui_actions_on_window_move_to (GtkAction *action,
187                                                  TnyList *list_to_move,
188                                                  TnyFolderStore *dst_folder,
189                                                  ModestWindow *win);
190
191 /*
192  * This function checks whether a TnyFolderStore is a pop account
193  */
194 static gboolean
195 remote_folder_has_leave_on_server (TnyFolderStore *folder)
196 {
197         TnyAccount *account;
198         gboolean result;
199
200         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
201
202         account = get_account_from_folder_store (folder);
203         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
204                                                                               modest_tny_account_get_protocol_type (account)));
205         g_object_unref (account);
206
207         return result;
208 }
209
210 /* FIXME: this should be merged with the similar code in modest-account-view-window */
211 /* Show the account creation wizard dialog.
212  * returns: TRUE if an account was created. FALSE if the user cancelled.
213  */
214 gboolean
215 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
216 {
217         gboolean result = FALSE;
218         GtkWindow *wizard;
219         gint dialog_response;
220
221         /* there is no such wizard yet */
222         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
223         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
224
225 #ifndef MODEST_TOOLKIT_HILDON2
226         /* always present a main window in the background
227          * we do it here, so we cannot end up with two wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win)
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
231                                                          TRUE);  /* create if not existent */
232 #else
233         if (!win) {
234                 GList *window_list;
235                 ModestWindowMgr *mgr;
236
237                 mgr = modest_runtime_get_window_mgr ();
238
239                 window_list = modest_window_mgr_get_window_list (mgr);
240                 if (window_list == NULL) {
241                         win = MODEST_WINDOW (modest_accounts_window_new ());
242                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
243                                 gtk_widget_show_all (GTK_WIDGET (win));
244                         } else {
245                                 gtk_widget_destroy (GTK_WIDGET (win));
246                                 win = NULL;
247                         }
248
249                 } else {
250                         g_list_free (window_list);
251                 }
252         }
253 #endif
254
255         if (win)
256                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
257
258         /* make sure the mainwindow is visible. We need to present the
259            wizard again to give it the focus back. show_all are needed
260            in order to get the widgets properly drawn (MainWindow main
261            paned won't be in its right position and the dialog will be
262            missplaced */
263 #ifndef MODEST_TOOLKIT_HILDON2
264         gtk_widget_show_all (GTK_WIDGET (win));
265         gtk_widget_show_all (GTK_WIDGET (wizard));
266         gtk_window_present (GTK_WINDOW (win));
267         gtk_window_present (GTK_WINDOW (wizard));
268 #endif
269
270         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
271         gtk_widget_destroy (GTK_WIDGET (wizard));
272         if (gtk_events_pending ())
273                 gtk_main_iteration ();
274
275         if (dialog_response == GTK_RESPONSE_CANCEL) {
276                 result = FALSE;
277         } else {
278                 /* Check whether an account was created: */
279                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
280         }
281         return result;
282 }
283
284
285 void
286 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
287 {
288         GtkWidget *about;
289         const gchar *authors[] = {
290                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
291                 NULL
292         };
293         about = gtk_about_dialog_new ();
294         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
295         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
296         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
297                                         _("Copyright (c) 2006, Nokia Corporation\n"
298                                           "All rights reserved."));
299         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
300                                        _("a modest e-mail client\n\n"
301                                          "design and implementation: Dirk-Jan C. Binnema\n"
302                                          "contributions from the fine people at KC and Ig\n"
303                                          "uses the tinymail email framework written by Philip van Hoof"));
304         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
305         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
306         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
307         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
308
309         gtk_dialog_run (GTK_DIALOG (about));
310         gtk_widget_destroy(about);
311 }
312
313 /*
314  * Gets the list of currently selected messages. If the win is the
315  * main window, then it returns a newly allocated list of the headers
316  * selected in the header view. If win is the msg view window, then
317  * the value returned is a list with just a single header.
318  *
319  * The caller of this funcion must free the list.
320  */
321 static TnyList *
322 get_selected_headers (ModestWindow *win)
323 {
324         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
325                 /* for MsgViewWindows, we simply return a list with one element */
326                 TnyHeader *header;
327                 TnyList *list = NULL;
328
329                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
330                 if (header != NULL) {
331                         list = tny_simple_list_new ();
332                         tny_list_prepend (list, G_OBJECT(header));
333                         g_object_unref (G_OBJECT(header));
334                 }
335
336                 return list;
337 #ifndef MODEST_TOOLKIT_HILDON2
338         } else if (MODEST_IS_MAIN_WINDOW(win)) {
339                 GtkWidget *header_view;
340
341                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
342                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
343                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
344 #else
345         } else if (MODEST_IS_HEADER_WINDOW (win)) {
346                 GtkWidget *header_view;
347
348                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
349                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
350 #endif
351         } else {
352                 return NULL;
353         }
354 }
355
356 #ifndef MODEST_TOOLKIT_HILDON2
357 static GtkTreeRowReference *
358 get_next_after_selected_headers (ModestHeaderView *header_view)
359 {
360         GtkTreeSelection *sel;
361         GList *selected_rows, *node;
362         GtkTreePath *path;
363         GtkTreeRowReference *result;
364         GtkTreeModel *model;
365
366         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
367         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
368         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
369
370         if (selected_rows == NULL)
371                 return NULL;
372
373         node = g_list_last (selected_rows);
374         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
375         gtk_tree_path_next (path);
376
377         result = gtk_tree_row_reference_new (model, path);
378
379         gtk_tree_path_free (path);
380         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
381         g_list_free (selected_rows);
382
383         return result;
384 }
385 #endif
386
387 static void
388 headers_action_mark_as_read (TnyHeader *header,
389                              ModestWindow *win,
390                              gpointer user_data)
391 {
392         TnyHeaderFlags flags;
393
394         g_return_if_fail (TNY_IS_HEADER(header));
395
396         flags = tny_header_get_flags (header);
397         if (flags & TNY_HEADER_FLAG_SEEN) return;
398         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
399 }
400
401 static void
402 headers_action_mark_as_unread (TnyHeader *header,
403                                ModestWindow *win,
404                                gpointer user_data)
405 {
406         TnyHeaderFlags flags;
407
408         g_return_if_fail (TNY_IS_HEADER(header));
409
410         flags = tny_header_get_flags (header);
411         if (flags & TNY_HEADER_FLAG_SEEN)  {
412                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
413         }
414 }
415
416 /** After deleing a message that is currently visible in a window,
417  * show the next message from the list, or close the window if there are no more messages.
418  **/
419 void
420 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
421 {
422         /* Close msg view window or select next */
423         if (!modest_msg_view_window_select_next_message (win) &&
424             !modest_msg_view_window_select_previous_message (win)) {
425                 gboolean ret_value;
426                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
427         }
428 }
429
430
431 void
432 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
433 {
434         modest_ui_actions_on_edit_mode_delete_message (win);
435 }
436
437 gboolean
438 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
439 {
440         TnyList *header_list = NULL;
441         TnyIterator *iter = NULL;
442         TnyHeader *header = NULL;
443         gchar *message = NULL;
444         gchar *desc = NULL;
445         gint response;
446         ModestWindowMgr *mgr;
447         gboolean retval = TRUE;
448
449         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
450
451         /* Get the headers, either from the header view (if win is the main window),
452          * or from the message view window: */
453         header_list = get_selected_headers (win);
454         if (!header_list) return FALSE;
455
456         /* Check if any of the headers are already opened, or in the process of being opened */
457
458         /* Select message */
459         if (tny_list_get_length(header_list) == 1) {
460                 iter = tny_list_create_iterator (header_list);
461                 header = TNY_HEADER (tny_iterator_get_current (iter));
462                 if (header) {
463                         gchar *subject;
464                         subject = tny_header_dup_subject (header);
465                         if (!subject)
466                                 subject = g_strdup (_("mail_va_no_subject"));
467                         desc = g_strdup_printf ("%s", subject);
468                         g_free (subject);
469                         g_object_unref (header);
470                 }
471
472                 g_object_unref (iter);
473         }
474         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
475                                            tny_list_get_length(header_list)), desc);
476
477         /* Confirmation dialog */
478         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
479                                                             message);
480
481         if (response == GTK_RESPONSE_OK) {
482                 GtkTreeSelection *sel = NULL;
483                 GList *sel_list = NULL;
484                 ModestMailOperation *mail_op = NULL;
485
486                 /* Find last selected row */
487
488                 /* Disable window dimming management */
489                 modest_window_disable_dimming (win);
490
491                 /* Remove each header. If it's a view window header_view == NULL */
492                 mail_op = modest_mail_operation_new ((GObject *) win);
493                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
494                                                  mail_op);
495                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
496                 g_object_unref (mail_op);
497
498                 /* Enable window dimming management */
499                 if (sel != NULL) {
500                         gtk_tree_selection_unselect_all (sel);
501                 }
502                 modest_window_enable_dimming (win);
503
504                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
505                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
506
507                         /* Get main window */
508                         mgr = modest_runtime_get_window_mgr ();
509                 }
510
511                 /* Update toolbar dimming state */
512                 modest_ui_actions_check_menu_dimming_rules (win);
513                 modest_ui_actions_check_toolbar_dimming_rules (win);
514
515                 /* Free */
516                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
517                 g_list_free (sel_list);
518                 retval = TRUE;
519         } else {
520                 retval = FALSE;
521         }
522
523         /* Free*/
524         g_free(message);
525         g_free(desc);
526         g_object_unref (header_list);
527
528         return retval;
529 }
530
531
532
533
534 /* delete either message or folder, based on where we are */
535 void
536 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
537 {
538         g_return_if_fail (MODEST_IS_WINDOW(win));
539
540         /* Check first if the header view has the focus */
541 #ifndef MODEST_TOOLKIT_HILDON2
542         if (MODEST_IS_MAIN_WINDOW (win)) {
543                 GtkWidget *w;
544                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
545                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
546                 if (gtk_widget_is_focus (w)) {
547                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
548                         return;
549                 }
550         }
551 #endif
552         modest_ui_actions_on_delete_message (action, win);
553 }
554
555 void
556 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
557 {
558         ModestWindowMgr *mgr = NULL;
559
560 #ifdef MODEST_PLATFORM_MAEMO
561         modest_window_mgr_save_state_for_all_windows (modest_runtime_get_window_mgr ());
562 #endif /* MODEST_PLATFORM_MAEMO */
563
564         g_debug ("closing down, clearing %d item(s) from operation queue",
565                  modest_mail_operation_queue_num_elements
566                  (modest_runtime_get_mail_operation_queue()));
567
568         /* cancel all outstanding operations */
569         modest_mail_operation_queue_cancel_all
570                 (modest_runtime_get_mail_operation_queue());
571
572         g_debug ("queue has been cleared");
573
574
575         /* Check if there are opened editing windows */
576         mgr = modest_runtime_get_window_mgr ();
577         modest_window_mgr_close_all_windows (mgr);
578
579         /* note: when modest-tny-account-store is finalized,
580            it will automatically set all network connections
581            to offline */
582
583 /*      gtk_main_quit (); */
584 }
585
586 void
587 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
588 {
589         gboolean ret_value;
590
591         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
592
593 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
594 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
595 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
596 /*              gboolean ret_value; */
597 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
598 /*      } else if (MODEST_IS_WINDOW (win)) { */
599 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
600 /*      } else { */
601 /*              g_return_if_reached (); */
602 /*      } */
603 }
604
605 void
606 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
607 {
608         if (MODEST_IS_MSG_VIEW_WINDOW (win))
609                 modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
610         else if (MODEST_IS_MSG_EDIT_WINDOW (win))
611                 modest_msg_edit_window_add_to_contacts (MODEST_MSG_EDIT_WINDOW (win));
612 }
613
614 void
615 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
616 {
617         GtkClipboard *clipboard = NULL;
618         gchar *selection = NULL;
619
620         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
621         selection = gtk_clipboard_wait_for_text (clipboard);
622
623         if (selection) {
624                 modest_address_book_add_address (selection, (GtkWindow *) win);
625                 g_free (selection);
626         }
627 }
628
629 void
630 modest_ui_actions_on_new_account (GtkAction *action,
631                                   ModestWindow *window)
632 {
633         if (!modest_ui_actions_run_account_setup_wizard (window)) {
634                 g_debug ("%s: wizard was already running", __FUNCTION__);
635         }
636 }
637
638 void
639 modest_ui_actions_on_accounts (GtkAction *action,
640                                ModestWindow *win)
641 {
642         /* This is currently only implemented for Maemo */
643         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
644                 if (!modest_ui_actions_run_account_setup_wizard (win))
645                         g_debug ("%s: wizard was already running", __FUNCTION__);
646
647                 return;
648         } else {
649                 /* Show the list of accounts */
650                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
651
652                 /* The accounts dialog must be modal */
653                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
654                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
655         }
656 }
657
658 void
659 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
660 {
661         /* This is currently only implemented for Maemo,
662          * because it requires an API (libconic) to detect different connection
663          * possiblities.
664          */
665 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
666
667         /* Create the window if necessary: */
668         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
669         modest_connection_specific_smtp_window_fill_with_connections (
670                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
671                 modest_runtime_get_account_mgr());
672
673         /* Show the window: */
674         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
675                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
676         gtk_widget_show (specific_window);
677 #endif /* !MODEST_TOOLKIT_GTK */
678 }
679
680 static guint64
681 count_part_size (const gchar *part)
682 {
683         GnomeVFSURI *vfs_uri;
684         gchar *escaped_filename;
685         gchar *filename;
686         GnomeVFSFileInfo *info;
687         guint64 result;
688
689         /* Estimation of attachment size if we cannot get it from file info */
690         result = 32768;
691
692         vfs_uri = gnome_vfs_uri_new (part);
693
694         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
695         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
696         g_free (escaped_filename);
697         gnome_vfs_uri_unref (vfs_uri);
698
699         info = gnome_vfs_file_info_new ();
700         
701         if (gnome_vfs_get_file_info (part, 
702                                      info, 
703                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
704             == GNOME_VFS_OK) {
705                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
706                         result = info->size;
707                 }
708         }
709         g_free (filename);
710         gnome_vfs_file_info_unref (info);
711
712         return result;
713 }
714
715 static guint64 
716 count_parts_size (GSList *parts)
717 {
718         GSList *node;
719         guint64 result = 0;
720
721         for (node = parts; node != NULL; node = g_slist_next (node)) {
722                 result += count_part_size ((const gchar *) node->data);
723         }
724
725         return result;
726 }
727
728 void
729 modest_ui_actions_compose_msg(ModestWindow *win,
730                               const gchar *to_str,
731                               const gchar *cc_str,
732                               const gchar *bcc_str,
733                               const gchar *subject_str,
734                               const gchar *body_str,
735                               GSList *attachments,
736                               gboolean set_as_modified)
737 {
738         gchar *account_name = NULL;
739         const gchar *mailbox;
740         TnyMsg *msg = NULL;
741         TnyAccount *account = NULL;
742         TnyFolder *folder = NULL;
743         gchar *from_str = NULL, *signature = NULL, *body = NULL;
744         gchar *recipient = NULL;
745         gboolean use_signature = FALSE;
746         ModestWindow *msg_win = NULL;
747         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
748         ModestTnyAccountStore *store = modest_runtime_get_account_store();
749         GnomeVFSFileSize total_size, allowed_size;
750         guint64 available_disk, expected_size, parts_size;
751         guint parts_count;
752
753         /* we check for low-mem */
754         if (modest_platform_check_memory_low (win, TRUE))
755                 goto cleanup;
756
757         available_disk = modest_utils_get_available_space (NULL);
758         parts_count = g_slist_length (attachments);
759         parts_size = count_parts_size (attachments);
760         expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
761
762         /* Double check: disk full condition or message too big */
763         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
764             expected_size > available_disk) {
765                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
766                 modest_platform_system_banner (NULL, NULL, msg);
767                 g_free (msg);
768
769                 return;
770         }
771
772         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
773                 modest_platform_run_information_dialog (
774                         GTK_WINDOW(win),
775                         _("mail_ib_error_attachment_size"),
776                         TRUE);
777                 return;
778         }
779
780
781 #ifdef MODEST_TOOLKIT_HILDON2
782         if (win)
783                 account_name = g_strdup (modest_window_get_active_account(win));
784 #endif
785         if (!account_name) {
786                 account_name = modest_account_mgr_get_default_account(mgr);
787         }
788         if (!account_name) {
789                 g_printerr ("modest: no account found\n");
790                 goto cleanup;
791         }
792
793         if (win)
794                 mailbox = modest_window_get_active_mailbox (win);
795         else
796                 mailbox = NULL;
797         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
798         if (!account) {
799                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
800                 goto cleanup;
801         }
802         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
803         if (!folder) {
804                 g_printerr ("modest: failed to find Drafts folder\n");
805                 goto cleanup;
806         }
807         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
808         if (!from_str) {
809                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
810                 goto cleanup;
811         }
812
813         recipient = modest_text_utils_get_email_address (from_str);
814         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
815         g_free (recipient);
816         if (body_str != NULL) {
817                 body = use_signature ? g_strconcat(body_str, "\n",
818                                                    MODEST_TEXT_UTILS_SIGNATURE_MARKER,
819                                                    "\n", signature, NULL) : g_strdup(body_str);
820         } else {
821                 body = use_signature ? g_strconcat("\n", MODEST_TEXT_UTILS_SIGNATURE_MARKER,
822                                                    "\n", signature, NULL) : g_strdup("");
823         }
824
825         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
826         if (!msg) {
827                 g_printerr ("modest: failed to create new msg\n");
828                 goto cleanup;
829         }
830
831         /* Create and register edit window */
832         /* This is destroyed by TODO. */
833         total_size = 0;
834         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
835         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
836
837         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
838                 gtk_widget_destroy (GTK_WIDGET (msg_win));
839                 goto cleanup;
840         }
841         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
842         gtk_widget_show_all (GTK_WIDGET (msg_win));
843
844         while (attachments) {
845                 GnomeVFSFileSize att_size;
846                 att_size =
847                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
848                                                                attachments->data, allowed_size);
849                 total_size += att_size;
850
851                 if (att_size > allowed_size) {
852                         g_debug ("%s: total size: %u",
853                                  __FUNCTION__, (unsigned int)total_size);
854                         break;
855                 }
856                 allowed_size -= att_size;
857
858                 attachments = g_slist_next(attachments);
859         }
860
861 cleanup:
862         g_free (from_str);
863         g_free (signature);
864         g_free (body);
865         g_free (account_name);
866         if (account)
867                 g_object_unref (G_OBJECT(account));
868         if (folder)
869                 g_object_unref (G_OBJECT(folder));
870         if (msg)
871                 g_object_unref (G_OBJECT(msg));
872 }
873
874 void
875 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
876 {
877         /* if there are no accounts yet, just show the wizard */
878         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
879                 if (!modest_ui_actions_run_account_setup_wizard (win))
880                         return;
881
882         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
883 }
884
885
886 gboolean
887 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
888                                        TnyHeader *header,
889                                        TnyMsg *msg)
890 {
891         ModestMailOperationStatus status;
892
893         /* If there is no message or the operation was not successful */
894         status = modest_mail_operation_get_status (mail_op);
895         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
896                 const GError *error;
897
898                 /* If it's a memory low issue, then show a banner */
899                 error = modest_mail_operation_get_error (mail_op);
900                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
901                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
902                         GObject *source = modest_mail_operation_get_source (mail_op);
903                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
904                                                                 _KR("memr_ib_operation_disabled"),
905                                                                 TRUE);
906                         g_object_unref (source);
907                 }
908
909                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
910                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
911                         gchar *subject, *msg, *format = NULL;
912                         TnyAccount *account;
913
914                         subject = (header) ? tny_header_dup_subject (header) : NULL;
915                         if (!subject)
916                                 subject = g_strdup (_("mail_va_no_subject"));
917
918                         account = modest_mail_operation_get_account (mail_op);
919                         if (account) {
920                                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
921                                 ModestProtocol *protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
922
923                                 if (protocol) {
924                                         if (tny_account_get_connection_status (account) ==
925                                             TNY_CONNECTION_STATUS_CONNECTED) {
926                                                 if (header) {
927                                                         format = modest_protocol_get_translation (protocol,
928                                                                                                   MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE,
929                                                                                                   subject);
930                                                 } else {
931                                                         format = modest_protocol_get_translation (protocol,
932                                                                                                   MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE_LOST_HEADER);
933                                                 }
934                                         } else {
935                                                 format = g_strdup_printf (_("mail_ib_backend_server_invalid"),
936                                                                           tny_account_get_hostname (account));
937                                         }
938                                 }
939                                 g_object_unref (account);
940                         }
941
942                         if (!format) {
943                                 if (header) {
944                                         format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
945                                 } else {
946                                         format = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
947                                 }
948                         }
949
950                         msg = g_strdup_printf (format, subject);
951                         modest_platform_run_information_dialog (NULL, msg, FALSE);
952                         g_free (msg);
953                         g_free (format);
954                         g_free (subject);
955                 }
956
957                 /* Remove the header from the preregistered uids */
958                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
959                                                      header);
960
961                 return FALSE;
962         }
963
964         return TRUE;
965 }
966
967 typedef struct {
968         guint idle_handler;
969         gchar *message;
970         GtkWidget *banner;
971 } OpenMsgBannerInfo;
972
973 typedef struct {
974         GtkTreeModel *model;
975         TnyHeader *header;
976         ModestWindow *caller_window;
977         OpenMsgBannerInfo *banner_info;
978         GtkTreeRowReference *rowref;
979 } OpenMsgHelper;
980
981 gboolean
982 open_msg_banner_idle (gpointer userdata)
983 {
984         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
985
986         gdk_threads_enter ();
987         banner_info->idle_handler = 0;
988         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
989         if (banner_info->banner)
990                 g_object_ref (banner_info->banner);
991
992         gdk_threads_leave ();
993
994         return FALSE;
995 }
996
997 static GtkWidget *
998 get_header_view_from_window (ModestWindow *window)
999 {
1000         GtkWidget *header_view;
1001
1002 #ifndef MODEST_TOOLKIT_HILDON2
1003         if (MODEST_IS_MAIN_WINDOW (window)) {
1004                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1005                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1006 #else
1007         if (MODEST_IS_HEADER_WINDOW (window)){
1008                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1009 #endif
1010         } else {
1011                 header_view = NULL;
1012         }
1013
1014         return header_view;
1015 }
1016
1017 static gchar *
1018 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1019 {
1020         TnyFolder *folder;
1021         gchar *account = NULL;
1022         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1023
1024         *is_draft = FALSE;
1025         *can_open = TRUE;
1026
1027         folder = tny_header_get_folder (header);
1028         /* Gets folder type (OUTBOX headers will be opened in edit window */
1029         if (modest_tny_folder_is_local_folder (folder)) {
1030                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1031                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1032                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1033         }
1034
1035         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1036                 TnyTransportAccount *traccount = NULL;
1037                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1038                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1039                 if (traccount) {
1040                         ModestTnySendQueue *send_queue = NULL;
1041                         ModestTnySendQueueStatus status;
1042                         gchar *msg_id;
1043                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1044                                                    TNY_ACCOUNT(traccount)));
1045                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1046                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1047                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1048                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1049                                 g_free (msg_id);
1050                                 /* Only open messages in outbox with the editor if they are in Failed state */
1051                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1052                                         *is_draft = TRUE;
1053                                 }
1054 #ifdef MODEST_TOOLKIT_HILDON2
1055                                 else {
1056                                         /* In Fremantle we can not
1057                                            open any message from
1058                                            outbox which is not in
1059                                            failed state */
1060                                         *can_open = FALSE;
1061                                 }
1062 #endif
1063                         }
1064                         g_object_unref(traccount);
1065                 } else {
1066                         g_warning("Cannot get transport account for message in outbox!!");
1067                 }
1068         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1069                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1070         }
1071
1072         if (!account) {
1073                 TnyAccount *acc = tny_folder_get_account (folder);
1074                 if (acc) {
1075                         account =
1076                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1077                         g_object_unref (acc);
1078                 }
1079         }
1080
1081         g_object_unref (folder);
1082
1083         return account;
1084 }
1085
1086 static void
1087 open_msg_cb (ModestMailOperation *mail_op,
1088              TnyHeader *header,
1089              gboolean canceled,
1090              TnyMsg *msg,
1091              GError *err,
1092              gpointer user_data)
1093 {
1094         ModestWindowMgr *mgr = NULL;
1095         ModestWindow *parent_win = NULL;
1096         ModestWindow *win = NULL;
1097         gchar *account = NULL;
1098         gboolean open_in_editor = FALSE;
1099         gboolean can_open;
1100         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1101
1102         /* Do nothing if there was any problem with the mail
1103            operation. The error will be shown by the error_handler of
1104            the mail operation */
1105         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1106                 return;
1107
1108         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1109
1110         /* Mark header as read */
1111         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1112
1113         account = get_info_from_header (header, &open_in_editor, &can_open);
1114
1115         /* Get account */
1116         if (!account)
1117                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1118         if (!account)
1119                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1120
1121         if (open_in_editor) {
1122                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1123                 gchar *from_header = NULL, *acc_name;
1124                 gchar *mailbox = NULL;
1125
1126                 from_header = tny_header_dup_from (header);
1127
1128                 /* we cannot edit without a valid account... */
1129                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1130                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1131                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1132                                                                      header);
1133                                 g_free (from_header);
1134                                 goto cleanup;
1135                         }
1136                 }
1137
1138                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1139                 g_free (from_header);
1140                 if (acc_name) {
1141                         g_free (account);
1142                         account = acc_name;
1143                 }
1144
1145                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1146                 if (mailbox)
1147                         g_free (mailbox);
1148         } else {
1149                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1150                 const gchar *mailbox = NULL;
1151
1152                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1153                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1154
1155                 if (helper->rowref && helper->model) {
1156                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1157                                                                             helper->model, helper->rowref);
1158                 } else {
1159                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1160                 }
1161                 g_free (uid);
1162         }
1163
1164         /* Register and show new window */
1165         if (win != NULL) {
1166                 mgr = modest_runtime_get_window_mgr ();
1167                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1168                         gtk_widget_destroy (GTK_WIDGET (win));
1169                         goto cleanup;
1170                 }
1171                 gtk_widget_show_all (GTK_WIDGET(win));
1172         }
1173
1174 #ifndef MODEST_TOOLKIT_HILDON2
1175         /* Update toolbar dimming state */
1176         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1177                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1178         }
1179 #endif
1180
1181 cleanup:
1182         /* Free */
1183         g_free(account);
1184         g_object_unref (parent_win);
1185 }
1186
1187 void
1188 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1189                                                  gpointer user_data)
1190 {
1191         const GError *error;
1192         GObject *win = NULL;
1193         ModestMailOperationStatus status;
1194
1195         win = modest_mail_operation_get_source (mail_op);
1196         error = modest_mail_operation_get_error (mail_op);
1197         status = modest_mail_operation_get_status (mail_op);
1198
1199         /* If the mail op has been cancelled then it's not an error:
1200            don't show any message */
1201         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1202                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1203                 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1204                                                                  (GError *) error, account)) {
1205                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1206                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1207                         g_free (msg);
1208                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1209                         modest_platform_information_banner ((GtkWidget *) win,
1210                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1211                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1212                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1213                         modest_platform_information_banner ((GtkWidget *) win,
1214                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1215                 } else if (user_data) {
1216                         modest_platform_information_banner ((GtkWidget *) win,
1217                                                             NULL, user_data);
1218                 }
1219                 if (account)
1220                         g_object_unref (account);
1221         }
1222
1223         if (win)
1224                 g_object_unref (win);
1225 }
1226
1227 /**
1228  * Returns the account a list of headers belongs to. It returns a
1229  * *new* reference so don't forget to unref it
1230  */
1231 static TnyAccount*
1232 get_account_from_header_list (TnyList *headers)
1233 {
1234         TnyAccount *account = NULL;
1235
1236         if (tny_list_get_length (headers) > 0) {
1237                 TnyIterator *iter = tny_list_create_iterator (headers);
1238                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1239                 TnyFolder *folder = tny_header_get_folder (header);
1240
1241                 if (!folder) {
1242                         g_object_unref (header);
1243
1244                         while (!tny_iterator_is_done (iter)) {
1245                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1246                                 folder = tny_header_get_folder (header);
1247                                 if (folder)
1248                                         break;
1249                                 g_object_unref (header);
1250                                 header = NULL;
1251                                 tny_iterator_next (iter);
1252                         }
1253                 }
1254
1255                 if (folder) {
1256                         account = tny_folder_get_account (folder);
1257                         g_object_unref (folder);
1258                 }
1259
1260                 if (header)
1261                         g_object_unref (header);
1262
1263                 g_object_unref (iter);
1264         }
1265         return account;
1266 }
1267
1268 static TnyAccount*
1269 get_account_from_header (TnyHeader *header)
1270 {
1271         TnyAccount *account = NULL;
1272         TnyFolder *folder;
1273
1274         folder = tny_header_get_folder (header);
1275
1276         if (folder) {
1277                 account = tny_folder_get_account (folder);
1278                 g_object_unref (folder);
1279         }
1280         return account;
1281 }
1282
1283 static void
1284 caller_win_destroyed (OpenMsgHelper *helper, GObject *object)
1285 {
1286         if (helper->caller_window)
1287                 helper->caller_window = NULL;
1288 }
1289
1290 static void
1291 open_msg_helper_destroyer (gpointer user_data)
1292 {
1293         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1294
1295         if (helper->caller_window) {
1296                 g_object_weak_unref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1297                 helper->caller_window = NULL;
1298         }
1299
1300         if (helper->banner_info) {
1301                 g_free (helper->banner_info->message);
1302                 if (helper->banner_info->idle_handler > 0) {
1303                         g_source_remove (helper->banner_info->idle_handler);
1304                         helper->banner_info->idle_handler = 0;
1305                 }
1306                 if (helper->banner_info->banner != NULL) {
1307                         gtk_widget_destroy (helper->banner_info->banner);
1308                         g_object_unref (helper->banner_info->banner);
1309                         helper->banner_info->banner = NULL;
1310                 }
1311                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1312                 helper->banner_info = NULL;
1313         }
1314         g_object_unref (helper->model);
1315         g_object_unref (helper->header);
1316         gtk_tree_row_reference_free (helper->rowref);
1317         g_slice_free (OpenMsgHelper, helper);
1318 }
1319
1320 static void
1321 open_msg_performer(gboolean canceled,
1322                     GError *err,
1323                     GtkWindow *parent_window,
1324                     TnyAccount *account,
1325                     gpointer user_data)
1326 {
1327         ModestMailOperation *mail_op = NULL;
1328         gchar *error_msg = NULL;
1329         ModestProtocolType proto;
1330         TnyConnectionStatus status;
1331         OpenMsgHelper *helper = NULL;
1332         ModestProtocol *protocol;
1333         ModestProtocolRegistry *protocol_registry;
1334         gchar *subject;
1335
1336         helper = (OpenMsgHelper *) user_data;
1337
1338         status = tny_account_get_connection_status (account);
1339         if (err || canceled || helper->caller_window == NULL) {
1340                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1341                 /* Free the helper */
1342                 open_msg_helper_destroyer (helper);
1343
1344                 /* In disk full conditions we could get this error here */
1345                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1346                                                                 (GtkWidget *) parent_window, err,
1347                                                                 account, NULL);
1348
1349                 goto clean;
1350         }
1351
1352         /* Get the error message depending on the protocol */
1353         proto = modest_tny_account_get_protocol_type (account);
1354         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1355                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1356         }
1357
1358         protocol_registry = modest_runtime_get_protocol_registry ();
1359         subject = tny_header_dup_subject (helper->header);
1360
1361         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1362         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1363         if (subject)
1364                 g_free (subject);
1365
1366         if (error_msg == NULL) {
1367                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1368         }
1369
1370 #ifndef MODEST_TOOLKIT_HILDON2
1371         gboolean show_open_draft = FALSE;
1372         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1373                                                             proto,
1374                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1375                 TnyFolder *folder;
1376                 TnyFolderType folder_type;
1377
1378                 folder = tny_header_get_folder (helper->header);
1379                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1380                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1381                 g_object_unref (folder);
1382         }
1383 #endif
1384
1385 #ifdef MODEST_TOOLKIT_HILDON2
1386         gboolean is_draft;
1387         gboolean can_open;
1388         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1389
1390         if (!can_open) {
1391                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1392                 g_free (account_name);
1393                 open_msg_helper_destroyer (helper);
1394                 goto clean;
1395         }
1396
1397         if (!is_draft) {
1398                 ModestWindow *window;
1399                 GtkWidget *header_view;
1400                 gchar *uid;
1401
1402                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1403                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1404                 if (header_view) {
1405                         const gchar *mailbox = NULL;
1406                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1407                         window = modest_msg_view_window_new_from_header_view 
1408                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1409                         if (window != NULL) {
1410                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1411                                                                         window, NULL)) {
1412                                         gtk_widget_destroy (GTK_WIDGET (window));
1413                                 } else {
1414                                         gtk_widget_show_all (GTK_WIDGET(window));
1415                                 }
1416                         }
1417                 }
1418                 g_free (account_name);
1419                 g_free (uid);
1420                 open_msg_helper_destroyer (helper);
1421                 goto clean;
1422         }
1423         g_free (account_name);
1424 #endif
1425         /* Create the mail operation */
1426         mail_op =
1427                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1428                                                                modest_ui_actions_disk_operations_error_handler,
1429                                                                g_strdup (error_msg), g_free);
1430         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1431                                          mail_op);
1432
1433
1434 #ifndef MODEST_TOOLKIT_HILDON2
1435         if (show_open_draft) {
1436                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1437                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1438                 helper->banner_info->banner = NULL;
1439                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1440                                                                    helper->banner_info);
1441         }
1442 #endif
1443
1444
1445         TnyList *headers;
1446         headers = TNY_LIST (tny_simple_list_new ());
1447         tny_list_prepend (headers, G_OBJECT (helper->header));
1448         modest_mail_operation_get_msgs_full (mail_op,
1449                                              headers,
1450                                              open_msg_cb,
1451                                              helper,
1452                                              open_msg_helper_destroyer);
1453         g_object_unref (headers);
1454
1455         /* Frees */
1456  clean:
1457         if (error_msg)
1458                 g_free (error_msg);
1459         if (mail_op)
1460                 g_object_unref (mail_op);
1461         g_object_unref (account);
1462 }
1463
1464 /*
1465  * This function is used by both modest_ui_actions_on_open and
1466  * modest_ui_actions_on_header_activated. This way we always do the
1467  * same when trying to open messages.
1468  */
1469 static void
1470 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1471 {
1472         ModestWindowMgr *mgr = NULL;
1473         TnyAccount *account;
1474         gboolean cached = FALSE;
1475         gboolean found;
1476         GtkWidget *header_view = NULL;
1477         OpenMsgHelper *helper;
1478         ModestWindow *window;
1479
1480         g_return_if_fail (header != NULL && rowref != NULL && gtk_tree_row_reference_valid (rowref));
1481
1482         mgr = modest_runtime_get_window_mgr ();
1483
1484         /* get model */
1485         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1486         if (header_view == NULL)
1487                 return;
1488
1489         /* Get the account */
1490         account = get_account_from_header (header);
1491         if (!account)
1492                 return;
1493
1494         window = NULL;
1495         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1496
1497         /* Do not open again the message and present the
1498            window to the user */
1499         if (found) {
1500                 if (window) {
1501 #ifndef MODEST_TOOLKIT_HILDON2
1502                         gtk_window_present (GTK_WINDOW (window));
1503 #endif
1504                 } else {
1505                         /* the header has been registered already, we don't do
1506                          * anything but wait for the window to come up*/
1507                         g_debug ("header %p already registered, waiting for window", header);
1508                 }
1509                 goto cleanup;
1510         }
1511
1512         /* Open each message */
1513         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1514         if (!cached) {
1515                 /* Allways download if we are online. */
1516                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1517                         gint response;
1518
1519                         /* If ask for user permission to download the messages */
1520                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1521                                                                             _("mcen_nc_get_msg"));
1522
1523                         /* End if the user does not want to continue */
1524                         if (response == GTK_RESPONSE_CANCEL) {
1525                                 goto cleanup;
1526                         }
1527                 }
1528         }
1529
1530         /* We register the window for opening */
1531         modest_window_mgr_register_header (mgr, header, NULL);
1532
1533         /* Create the helper. We need to get a reference to the model
1534            here because it could change while the message is readed
1535            (the user could switch between folders) */
1536         helper = g_slice_new (OpenMsgHelper);
1537         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1538         helper->caller_window = win;
1539         g_object_weak_ref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1540         helper->header = g_object_ref (header);
1541         helper->rowref = gtk_tree_row_reference_copy (rowref);
1542         helper->banner_info = NULL;
1543
1544         /* Connect to the account and perform */
1545         if (!cached) {
1546                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1547                                                      open_msg_performer, helper);
1548         } else {
1549                 /* Call directly the performer, do not need to connect */
1550                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1551                                     g_object_ref (account), helper);
1552         }
1553 cleanup:
1554         /* Clean */
1555         if (account)
1556                 g_object_unref (account);
1557 }
1558
1559 void
1560 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1561 {
1562         TnyList *headers;
1563         TnyHeader *header;
1564         gint headers_count;
1565         TnyIterator *iter;
1566
1567         /* we check for low-mem; in that case, show a warning, and don't allow
1568          * opening
1569          */
1570         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1571                 return;
1572
1573         /* Get headers */
1574         headers = get_selected_headers (win);
1575         if (!headers)
1576                 return;
1577
1578         headers_count = tny_list_get_length (headers);
1579         if (headers_count != 1) {
1580                 if (headers_count > 1) {
1581                         /* Don't allow activation if there are more than one message selected */
1582                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1583                 }
1584
1585                 g_object_unref (headers);
1586                 return;
1587         }
1588
1589         iter = tny_list_create_iterator (headers);
1590         header = TNY_HEADER (tny_iterator_get_current (iter));
1591         g_object_unref (iter);
1592
1593         /* Open them */
1594         if (header) {
1595                 open_msg_from_header (header, NULL, win);
1596                 g_object_unref (header);
1597         }
1598
1599         g_object_unref(headers);
1600 }
1601
1602 static void
1603 rf_helper_window_closed (gpointer data,
1604                          GObject *object)
1605 {
1606         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1607
1608         helper->parent_window = NULL;
1609 }
1610
1611 static ReplyForwardHelper*
1612 create_reply_forward_helper (ReplyForwardAction action,
1613                              ModestWindow *win,
1614                              guint reply_forward_type,
1615                              TnyHeader *header)
1616 {
1617         ReplyForwardHelper *rf_helper = NULL;
1618         const gchar *active_acc = modest_window_get_active_account (win);
1619         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1620
1621         rf_helper = g_slice_new0 (ReplyForwardHelper);
1622         rf_helper->reply_forward_type = reply_forward_type;
1623         rf_helper->action = action;
1624         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1625         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1626         rf_helper->account_name = (active_acc) ?
1627                 g_strdup (active_acc) :
1628                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1629         rf_helper->mailbox = g_strdup (active_mailbox);
1630
1631         /* Note that window could be destroyed just AFTER calling
1632            register_window so we must ensure that this pointer does
1633            not hold invalid references */
1634         if (rf_helper->parent_window)
1635                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1636                                    rf_helper_window_closed, rf_helper);
1637
1638         return rf_helper;
1639 }
1640
1641 static void
1642 free_reply_forward_helper (gpointer data)
1643 {
1644         ReplyForwardHelper *helper;
1645
1646         helper = (ReplyForwardHelper *) data;
1647         g_free (helper->account_name);
1648         g_free (helper->mailbox);
1649         if (helper->header)
1650                 g_object_unref (helper->header);
1651         if (helper->parent_window)
1652                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1653                                      rf_helper_window_closed, helper);
1654         g_slice_free (ReplyForwardHelper, helper);
1655 }
1656
1657 static void
1658 reply_forward_cb (ModestMailOperation *mail_op,
1659                   TnyHeader *header,
1660                   gboolean canceled,
1661                   TnyMsg *msg,
1662                   GError *err,
1663                   gpointer user_data)
1664 {
1665         TnyMsg *new_msg = NULL;
1666         ReplyForwardHelper *rf_helper;
1667         ModestWindow *msg_win = NULL;
1668         ModestEditType edit_type;
1669         gchar *from = NULL;
1670         TnyAccount *account = NULL;
1671         ModestWindowMgr *mgr = NULL;
1672         gchar *signature = NULL;
1673         gboolean use_signature;
1674         gchar *recipient;
1675
1676         /* If there was any error. The mail operation could be NULL,
1677            this means that we already have the message downloaded and
1678            that we didn't do a mail operation to retrieve it */
1679         rf_helper = (ReplyForwardHelper *) user_data;
1680         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1681                 goto cleanup;
1682
1683         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1684                                                    rf_helper->account_name, rf_helper->mailbox);
1685         recipient = modest_text_utils_get_email_address (from);
1686         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1687                                                                      recipient, 
1688                                                                      &use_signature);
1689         g_free (recipient);
1690
1691         /* Create reply mail */
1692         switch (rf_helper->action) {
1693                 /* Use the msg_header to ensure that we have all the
1694                    information. The summary can lack some data */
1695                 TnyHeader *msg_header;
1696         case ACTION_REPLY:
1697                 msg_header = tny_msg_get_header (msg);
1698                 new_msg =
1699                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1700                                                          (use_signature) ? signature : NULL,
1701                                                          rf_helper->reply_forward_type,
1702                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1703                 g_object_unref (msg_header);
1704                 break;
1705         case ACTION_REPLY_TO_ALL:
1706                 msg_header = tny_msg_get_header (msg);
1707                 new_msg =
1708                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1709                                                          (use_signature) ? signature : NULL,
1710                                                          rf_helper->reply_forward_type,
1711                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1712                 edit_type = MODEST_EDIT_TYPE_REPLY;
1713                 g_object_unref (msg_header);
1714                 break;
1715         case ACTION_FORWARD:
1716                 new_msg =
1717                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1718                                                            rf_helper->reply_forward_type);
1719                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1720                 break;
1721         default:
1722                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1723                                                      header);
1724                 g_return_if_reached ();
1725                 return;
1726         }
1727
1728         g_free (from);
1729         g_free (signature);
1730
1731         if (!new_msg) {
1732                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1733                 goto cleanup;
1734         }
1735
1736         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1737                                                                        rf_helper->account_name,
1738                                                                        TNY_ACCOUNT_TYPE_STORE);
1739         if (!account) {
1740                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1741                 goto cleanup;
1742         }
1743
1744         /* Create and register the windows */
1745         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1746         mgr = modest_runtime_get_window_mgr ();
1747         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1748
1749         /* Note that register_window could have deleted the account */
1750         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1751                 gdouble parent_zoom;
1752
1753                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1754                 modest_window_set_zoom (msg_win, parent_zoom);
1755         }
1756
1757         /* Show edit window */
1758         gtk_widget_show_all (GTK_WIDGET (msg_win));
1759
1760 cleanup:
1761         /* We always unregister the header because the message is
1762            forwarded or replied so the original one is no longer
1763            opened */
1764         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1765                                              header);
1766         if (new_msg)
1767                 g_object_unref (G_OBJECT (new_msg));
1768         if (account)
1769                 g_object_unref (G_OBJECT (account));
1770         free_reply_forward_helper (rf_helper);
1771 }
1772
1773 /* Checks a list of headers. If any of them are not currently
1774  * downloaded (CACHED) then returns TRUE else returns FALSE.
1775  */
1776 static gint
1777 header_list_count_uncached_msgs (TnyList *header_list)
1778 {
1779         TnyIterator *iter;
1780         gint uncached_messages = 0;
1781
1782         iter = tny_list_create_iterator (header_list);
1783         while (!tny_iterator_is_done (iter)) {
1784                 TnyHeader *header;
1785
1786                 header = TNY_HEADER (tny_iterator_get_current (iter));
1787                 if (header) {
1788                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1789                                 uncached_messages ++;
1790                         g_object_unref (header);
1791                 }
1792
1793                 tny_iterator_next (iter);
1794         }
1795         g_object_unref (iter);
1796
1797         return uncached_messages;
1798 }
1799
1800 /* Returns FALSE if the user does not want to download the
1801  * messages. Returns TRUE if the user allowed the download.
1802  */
1803 static gboolean
1804 connect_to_get_msg (ModestWindow *win,
1805                     gint num_of_uncached_msgs,
1806                     TnyAccount *account)
1807 {
1808         GtkResponseType response;
1809
1810         /* Allways download if we are online. */
1811         if (tny_device_is_online (modest_runtime_get_device ()))
1812                 return TRUE;
1813
1814         /* If offline, then ask for user permission to download the messages */
1815         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1816                         ngettext("mcen_nc_get_msg",
1817                         "mcen_nc_get_msgs",
1818                         num_of_uncached_msgs));
1819
1820         if (response == GTK_RESPONSE_CANCEL)
1821                 return FALSE;
1822
1823         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1824 }
1825
1826 static void
1827 reply_forward_performer (gboolean canceled,
1828                          GError *err,
1829                          GtkWindow *parent_window,
1830                          TnyAccount *account,
1831                          gpointer user_data)
1832 {
1833         ReplyForwardHelper *rf_helper = NULL;
1834         ModestMailOperation *mail_op;
1835
1836         rf_helper = (ReplyForwardHelper *) user_data;
1837
1838         if (canceled || err) {
1839                 free_reply_forward_helper (rf_helper);
1840                 return;
1841         }
1842
1843         /* Retrieve the message */
1844         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1845         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1846                                                                  modest_ui_actions_disk_operations_error_handler,
1847                                                                  NULL, NULL);
1848         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1849         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1850
1851         /* Frees */
1852         g_object_unref(mail_op);
1853 }
1854
1855 /*
1856  * Common code for the reply and forward actions
1857  */
1858 static void
1859 reply_forward (ReplyForwardAction action, ModestWindow *win)
1860 {
1861         ReplyForwardHelper *rf_helper = NULL;
1862         guint reply_forward_type;
1863
1864         g_return_if_fail (win && MODEST_IS_WINDOW(win));
1865
1866         /* we check for low-mem; in that case, show a warning, and don't allow
1867          * reply/forward (because it could potentially require a lot of memory */
1868         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1869                 return;
1870
1871
1872         /* we need an account when editing */
1873         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1874                 if (!modest_ui_actions_run_account_setup_wizard (win))
1875                         return;
1876         }
1877
1878         reply_forward_type =
1879                 modest_conf_get_int (modest_runtime_get_conf (),
1880                                      (action == ACTION_FORWARD) ?
1881                                      MODEST_CONF_FORWARD_TYPE :
1882                                      MODEST_CONF_REPLY_TYPE,
1883                                      NULL);
1884
1885         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1886                 TnyMsg *msg = NULL;
1887                 TnyHeader *header = NULL;
1888                 /* Get header and message. Do not free them here, the
1889                    reply_forward_cb must do it */
1890                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1891                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1892
1893                 if (msg && header) {
1894                         /* Create helper */
1895                         rf_helper = create_reply_forward_helper (action, win,
1896                                                                  reply_forward_type, header);
1897                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1898                 } else {
1899                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1900                 }
1901
1902                 if (msg)
1903                         g_object_unref (msg);
1904                 if (header)
1905                         g_object_unref (header);
1906         } else {
1907                 TnyHeader *header = NULL;
1908                 TnyIterator *iter;
1909                 gboolean do_retrieve = TRUE;
1910                 TnyList *header_list = NULL;
1911
1912                 header_list = get_selected_headers (win);
1913                 if (!header_list)
1914                         return;
1915                 /* Check that only one message is selected for replying */
1916                 if (tny_list_get_length (header_list) != 1) {
1917                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1918                                                             NULL, _("mcen_ib_select_one_message"));
1919                         g_object_unref (header_list);
1920                         return;
1921                 }
1922
1923                 /* Only reply/forward to one message */
1924                 iter = tny_list_create_iterator (header_list);
1925                 header = TNY_HEADER (tny_iterator_get_current (iter));
1926                 g_object_unref (iter);
1927
1928                 /* Retrieve messages */
1929                 do_retrieve = (action == ACTION_FORWARD) ||
1930                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1931
1932                 if (do_retrieve) {
1933                         TnyAccount *account = NULL;
1934                         TnyFolder *folder = NULL;
1935                         gdouble download = TRUE;
1936                         guint uncached_msgs = 0;
1937
1938                         folder = tny_header_get_folder (header);
1939                         if (!folder)
1940                                 goto do_retrieve_frees;
1941                         account = tny_folder_get_account (folder);
1942                         if (!account)
1943                                 goto do_retrieve_frees;
1944
1945                         uncached_msgs = header_list_count_uncached_msgs (header_list);
1946
1947                         if (uncached_msgs > 0) {
1948                                 /* Allways download if we are online. */
1949                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1950                                         gint response;
1951
1952                                         /* If ask for user permission to download the messages */
1953                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1954                                                                                             ngettext("mcen_nc_get_msg",
1955                                                                                                      "mcen_nc_get_msgs",
1956                                                                                                      uncached_msgs));
1957
1958                                         /* End if the user does not want to continue */
1959                                         if (response == GTK_RESPONSE_CANCEL)
1960                                                 download = FALSE;
1961                                 }
1962                         }
1963
1964                         if (download) {
1965                                 /* Create helper */
1966                                 rf_helper = create_reply_forward_helper (action, win,
1967                                                                          reply_forward_type, header);
1968                                 if (uncached_msgs > 0) {
1969                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
1970                                                                              TRUE, account,
1971                                                                              reply_forward_performer,
1972                                                                              rf_helper);
1973                                 } else {
1974                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
1975                                                                  account, rf_helper);
1976                                 }
1977                         }
1978                 do_retrieve_frees:
1979                         if (account)
1980                                 g_object_unref (account);
1981                         if (folder)
1982                                 g_object_unref (folder);
1983                 } else {
1984                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, NULL);
1985                 }
1986                 /* Frees */
1987                 g_object_unref (header_list);
1988                 g_object_unref (header);
1989         }
1990 }
1991
1992 void
1993 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1994 {
1995         g_return_if_fail (MODEST_IS_WINDOW(win));
1996
1997         reply_forward (ACTION_REPLY, win);
1998 }
1999
2000 void
2001 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2002 {
2003         g_return_if_fail (MODEST_IS_WINDOW(win));
2004
2005         reply_forward (ACTION_FORWARD, win);
2006 }
2007
2008 void
2009 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2010 {
2011         g_return_if_fail (MODEST_IS_WINDOW(win));
2012
2013         reply_forward (ACTION_REPLY_TO_ALL, win);
2014 }
2015
2016 void
2017 modest_ui_actions_on_next (GtkAction *action,
2018                            ModestWindow *window)
2019 {
2020 #ifndef MODEST_TOOLKIT_HILDON2
2021         if (MODEST_IS_MAIN_WINDOW (window)) {
2022                 GtkWidget *header_view;
2023
2024                 header_view = modest_main_window_get_child_widget (
2025                                 MODEST_MAIN_WINDOW(window),
2026                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2027                 if (!header_view)
2028                         return;
2029
2030                 modest_header_view_select_next (
2031                                 MODEST_HEADER_VIEW(header_view));
2032 #else
2033         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2034                 modest_msg_view_window_select_next_message (
2035                                 MODEST_MSG_VIEW_WINDOW (window));
2036 #endif
2037         } else {
2038                 g_return_if_reached ();
2039         }
2040 }
2041
2042 void
2043 modest_ui_actions_on_prev (GtkAction *action,
2044                            ModestWindow *window)
2045 {
2046         g_return_if_fail (MODEST_IS_WINDOW(window));
2047
2048 #ifndef MODEST_TOOLKIT_HILDON2
2049         if (MODEST_IS_MAIN_WINDOW (window)) {
2050                 GtkWidget *header_view;
2051                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2052                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2053                 if (!header_view)
2054                         return;
2055
2056                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2057 #else
2058         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2059                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2060 #endif
2061         } else {
2062                 g_return_if_reached ();
2063         }
2064 }
2065
2066 void
2067 modest_ui_actions_on_sort (GtkAction *action,
2068                            ModestWindow *window)
2069 {
2070         GtkWidget *header_view = NULL;
2071
2072         g_return_if_fail (MODEST_IS_WINDOW(window));
2073
2074 #ifndef MODEST_TOOLKIT_HILDON2
2075         if (MODEST_IS_MAIN_WINDOW (window)) {
2076                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2077                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2078 #else
2079         if (MODEST_IS_HEADER_WINDOW (window)) {
2080                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2081 #endif
2082         }
2083
2084         if (!header_view) {
2085                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2086
2087                 return;
2088         }
2089
2090         /* Show sorting dialog */
2091         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2092 }
2093
2094 static void
2095 sync_folder_cb (ModestMailOperation *mail_op,
2096                 TnyFolder *folder,
2097                 gpointer user_data)
2098 {
2099         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2100
2101         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
2102                 ModestWindow *parent = (ModestWindow *) modest_mail_operation_get_source (mail_op);
2103
2104                 /* We must clear first, because otherwise set_folder will ignore */
2105                 /*    the change as the folders are the same */
2106                 modest_header_view_clear (header_view);
2107                 modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL);
2108
2109                 g_object_unref (parent);
2110         }
2111
2112         g_object_unref (header_view);
2113 }
2114
2115 static gboolean
2116 idle_refresh_folder (gpointer source)
2117 {
2118         ModestHeaderView *header_view = NULL;
2119
2120         /* If the window still exists */
2121         if (!GTK_IS_WIDGET (source) ||
2122             !GTK_WIDGET_VISIBLE (source))
2123                 return FALSE;
2124
2125         /* Refresh the current view */
2126 #ifdef MODEST_TOOLKIT_HILDON2
2127         if (MODEST_IS_HEADER_WINDOW (source))
2128                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2129 #else
2130         if (MODEST_IS_MAIN_WINDOW (source))
2131                 header_view = MODEST_HEADER_VIEW (modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source),
2132                                                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
2133 #endif
2134         if (header_view) {
2135                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2136                 if (folder) {
2137                         /* Sync the folder status */
2138                         ModestMailOperation *mail_op = modest_mail_operation_new (source);
2139                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2140                         modest_mail_operation_sync_folder (mail_op, folder, FALSE, sync_folder_cb, g_object_ref (header_view));
2141                         g_object_unref (folder);
2142                         g_object_unref (mail_op);
2143                 }
2144         }
2145
2146         return FALSE;
2147 }
2148
2149 static void
2150 update_account_cb (ModestMailOperation *self,
2151                    TnyList *new_headers,
2152                    gpointer user_data)
2153 {
2154         ModestWindow *top;
2155         gboolean show_visual_notifications;
2156
2157         top = modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
2158         show_visual_notifications = (top) ? FALSE : TRUE;
2159
2160         /* Notify new messages have been downloaded. If the
2161            send&receive was invoked by the user then do not show any
2162            visual notification, only play a sound and activate the LED
2163            (for the Maemo version) */
2164         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2165
2166                 /* We only notify about really new messages (not seen) we get */
2167                 TnyList *actually_new_list;
2168                 TnyIterator *iterator;
2169                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2170                 for (iterator = tny_list_create_iterator (new_headers);
2171                      !tny_iterator_is_done (iterator);
2172                      tny_iterator_next (iterator)) {
2173                         TnyHeader *header;
2174                         TnyHeaderFlags flags;
2175                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2176                         flags = tny_header_get_flags (header);
2177
2178                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2179                                 /* Messages are ordered from most
2180                                    recent to oldest. But we want to
2181                                    show notifications starting from
2182                                    the oldest message. That's why we
2183                                    reverse the list */
2184                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2185                         }
2186                         g_object_unref (header);
2187                 }
2188                 g_object_unref (iterator);
2189
2190                 if (tny_list_get_length (actually_new_list) > 0) {
2191                         GList *new_headers_list = NULL;
2192
2193                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2194
2195                         /* Send notifications */
2196                         if (new_headers_list) {
2197                                 modest_platform_on_new_headers_received (new_headers_list,
2198                                                                          show_visual_notifications);
2199                                 /* Free the list */
2200                                 modest_utils_free_notification_list (new_headers_list);
2201                         }
2202                 }
2203                 g_object_unref (actually_new_list);
2204         }
2205
2206         if (top) {
2207                 /* Refresh the current folder in an idle. We do this
2208                    in order to avoid refresh cancelations if the
2209                    currently viewed folder is the inbox */
2210                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2211                                  idle_refresh_folder,
2212                                  g_object_ref (top),
2213                                  g_object_unref);
2214         }
2215 }
2216
2217 typedef struct {
2218         TnyAccount *account;
2219         ModestWindow *win;
2220         gchar *account_name;
2221         gboolean poke_status;
2222         gboolean interactive;
2223         ModestMailOperation *mail_op;
2224 } SendReceiveInfo;
2225
2226 static void
2227 do_send_receive_performer (gboolean canceled,
2228                            GError *err,
2229                            GtkWindow *parent_window,
2230                            TnyAccount *account,
2231                            gpointer user_data)
2232 {
2233         SendReceiveInfo *info;
2234
2235         info = (SendReceiveInfo *) user_data;
2236
2237         if (err || canceled) {
2238                 /* In disk full conditions we could get this error here */
2239                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2240                                                                 (GtkWidget *) parent_window, err,
2241                                                                 account, NULL);
2242
2243                 if (info->mail_op) {
2244                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2245                                                             info->mail_op);
2246                 }
2247                 goto clean;
2248         }
2249
2250 #ifndef MODEST_TOOLKIT_HILDON2
2251         /* Set send/receive operation in progress */
2252         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2253                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2254         }
2255
2256         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2257                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2258                                   G_CALLBACK (on_send_receive_finished),
2259                                   info->win);
2260 #endif
2261
2262         /* Send & receive. */
2263         modest_mail_operation_update_account (info->mail_op, info->account_name,
2264                                               info->poke_status, info->interactive,
2265                                               update_account_cb, info->win);
2266
2267  clean:
2268         /* Frees */
2269         if (info->mail_op)
2270                 g_object_unref (G_OBJECT (info->mail_op));
2271         if (info->account_name)
2272                 g_free (info->account_name);
2273         if (info->win)
2274                 g_object_unref (info->win);
2275         if (info->account)
2276                 g_object_unref (info->account);
2277         g_slice_free (SendReceiveInfo, info);
2278 }
2279
2280 /*
2281  * This function performs the send & receive required actions. The
2282  * window is used to create the mail operation. Typically it should
2283  * always be the main window, but we pass it as argument in order to
2284  * be more flexible.
2285  */
2286 void
2287 modest_ui_actions_do_send_receive (const gchar *account_name,
2288                                    gboolean force_connection,
2289                                    gboolean poke_status,
2290                                    gboolean interactive,
2291                                    ModestWindow *win)
2292 {
2293         gchar *acc_name = NULL;
2294         SendReceiveInfo *info;
2295         ModestTnyAccountStore *acc_store;
2296         TnyAccount *account;
2297
2298         /* If no account name was provided then get the current account, and if
2299            there is no current account then pick the default one: */
2300         if (!account_name) {
2301                 if (win)
2302                         acc_name = g_strdup (modest_window_get_active_account (win));
2303                 if (!acc_name)
2304                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2305                 if (!acc_name) {
2306                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2307                         return;
2308                 }
2309         } else {
2310                 acc_name = g_strdup (account_name);
2311         }
2312
2313         acc_store = modest_runtime_get_account_store ();
2314         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2315
2316         if (!account) {
2317                 g_free (acc_name);
2318                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2319                 return;
2320         }
2321
2322         /* Do not automatically refresh accounts that are flagged as
2323            NO_AUTO_UPDATE. This could be useful for accounts that
2324            handle their own update times */
2325         if (!interactive) {
2326                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2327                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2328                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2329                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2330
2331                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2332                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2333                                 g_object_unref (account);
2334                                 g_free (acc_name);
2335                                 return;
2336                         }
2337                 }
2338         }
2339
2340         /* Create the info for the connect and perform */
2341         info = g_slice_new (SendReceiveInfo);
2342         info->account_name = acc_name;
2343         info->win = (win) ? g_object_ref (win) : NULL;
2344         info->poke_status = poke_status;
2345         info->interactive = interactive;
2346         info->account = account;
2347         /* We need to create the operation here, because otherwise it
2348            could happen that the queue emits the queue-empty signal
2349            while we're trying to connect the account */
2350         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2351                                                                        modest_ui_actions_disk_operations_error_handler,
2352                                                                        NULL, NULL);
2353         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2354
2355         /* Invoke the connect and perform */
2356         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2357                                              force_connection, info->account,
2358                                              do_send_receive_performer, info);
2359 }
2360
2361
2362 static void
2363 modest_ui_actions_do_cancel_send (const gchar *account_name,
2364                                   ModestWindow *win)
2365 {
2366         TnyTransportAccount *transport_account;
2367         TnySendQueue *send_queue = NULL;
2368         GError *error = NULL;
2369
2370         /* Get transport account */
2371         transport_account =
2372                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2373                                       (modest_runtime_get_account_store(),
2374                                        account_name,
2375                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2376         if (!transport_account) {
2377                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2378                 goto frees;
2379         }
2380
2381         /* Get send queue*/
2382         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2383         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2384                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2385                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2386                              "modest: could not find send queue for account\n");
2387         } else {
2388                 /* Cancel the current send */
2389                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2390
2391                 /* Suspend all pending messages */
2392                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2393         }
2394
2395  frees:
2396         if (transport_account != NULL)
2397                 g_object_unref (G_OBJECT (transport_account));
2398 }
2399
2400 static void
2401 modest_ui_actions_cancel_send_all (ModestWindow *win)
2402 {
2403         GSList *account_names, *iter;
2404
2405         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2406                                                           TRUE);
2407
2408         iter = account_names;
2409         while (iter) {
2410                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2411                 iter = g_slist_next (iter);
2412         }
2413
2414         modest_account_mgr_free_account_names (account_names);
2415         account_names = NULL;
2416 }
2417
2418 void
2419 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2420
2421 {
2422         /* Check if accounts exist */
2423         gboolean accounts_exist =
2424                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2425
2426         /* If not, allow the user to create an account before trying to send/receive. */
2427         if (!accounts_exist)
2428                 modest_ui_actions_on_accounts (NULL, win);
2429
2430         /* Cancel all sending operaitons */
2431         modest_ui_actions_cancel_send_all (win);
2432 }
2433
2434 /*
2435  * Refreshes all accounts. This function will be used by automatic
2436  * updates
2437  */
2438 void
2439 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2440                                        gboolean force_connection,
2441                                        gboolean poke_status,
2442                                        gboolean interactive)
2443 {
2444         GSList *account_names, *iter;
2445
2446         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2447                                                           TRUE);
2448
2449         iter = account_names;
2450         while (iter) {
2451                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2452                                                    force_connection,
2453                                                    poke_status, interactive, win);
2454                 iter = g_slist_next (iter);
2455         }
2456
2457         modest_account_mgr_free_account_names (account_names);
2458         account_names = NULL;
2459 }
2460
2461 /*
2462  * Handler of the click on Send&Receive button in the main toolbar
2463  */
2464 void
2465 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2466 {
2467         /* Check if accounts exist */
2468         gboolean accounts_exist;
2469
2470         accounts_exist =
2471                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2472
2473         /* If not, allow the user to create an account before trying to send/receive. */
2474         if (!accounts_exist)
2475                 modest_ui_actions_on_accounts (NULL, win);
2476
2477         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2478 #ifndef MODEST_TOOLKIT_HILDON2
2479         if (MODEST_IS_MAIN_WINDOW (win)) {
2480                 GtkWidget *folder_view;
2481                 TnyFolderStore *folder_store;
2482
2483                 folder_view =
2484                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2485                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2486                 if (!folder_view)
2487                         return;
2488
2489                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2490
2491                 if (folder_store)
2492                         g_object_unref (folder_store);
2493                 /* Refresh the active account. Force the connection if needed
2494                    and poke the status of all folders */
2495                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2496 #else
2497         if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2498                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2499 #endif
2500         } else {
2501                 const gchar *active_account;
2502                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2503
2504                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2505         }
2506
2507 }
2508
2509 #ifndef MODEST_TOOLKIT_HILDON2
2510 void
2511 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2512 {
2513         ModestConf *conf;
2514         GtkWidget *header_view;
2515
2516         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2517
2518         header_view = modest_main_window_get_child_widget (main_window,
2519                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2520         if (!header_view)
2521                 return;
2522
2523         conf = modest_runtime_get_conf ();
2524
2525         /* what is saved/restored is depending on the style; thus; we save with
2526          * old style, then update the style, and restore for this new style
2527          */
2528         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2529
2530         if (modest_header_view_get_style
2531             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2532                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2533                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2534         else
2535                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2536                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2537
2538         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2539                                       MODEST_CONF_HEADER_VIEW_KEY);
2540 }
2541
2542 void
2543 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2544                                       TnyHeader *header,
2545                                       ModestMainWindow *main_window)
2546 {
2547         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2548         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2549
2550         /* in the case the folder is empty, show the empty folder message and focus
2551          * folder view */
2552         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2553                 if (modest_header_view_is_empty (header_view)) {
2554                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2555                         GtkWidget *folder_view =
2556                                 modest_main_window_get_child_widget (main_window,
2557                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2558                         if (folder != NULL) {
2559                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2560                                 g_object_unref (folder);
2561                         }
2562                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2563                         return;
2564                 }
2565         }
2566         /* If no header has been selected then exit */
2567         if (!header)
2568                 return;
2569
2570         /* Update focus */
2571         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2572             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2573
2574         /* Update toolbar dimming state */
2575         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2576         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2577 }
2578 #endif
2579
2580 void
2581 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2582                                        TnyHeader *header,
2583                                        GtkTreePath *path,
2584                                        ModestWindow *window)
2585 {
2586         GtkTreeRowReference *rowref;
2587
2588         g_return_if_fail (MODEST_IS_WINDOW(window));
2589         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2590         g_return_if_fail (TNY_IS_HEADER (header));
2591
2592         if (modest_header_view_count_selected_headers (header_view) > 1) {
2593                 /* Don't allow activation if there are more than one message selected */
2594                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2595                 return;
2596         }
2597
2598         /* we check for low-mem; in that case, show a warning, and don't allow
2599          * activating headers
2600          */
2601         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2602                 return;
2603
2604 #ifndef MODEST_TOOLKIT_HILDON2
2605         GtkWidget *open_widget;
2606         if (MODEST_IS_MAIN_WINDOW (window)) {
2607                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2608                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2609                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2610                         return;
2611         }
2612 #endif
2613
2614         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2615         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2616         gtk_tree_row_reference_free (rowref);
2617 }
2618
2619 #ifndef MODEST_TOOLKIT_HILDON2
2620 static void
2621 set_active_account_from_tny_account (TnyAccount *account,
2622                                      ModestWindow *window)
2623 {
2624         const gchar *server_acc_name = tny_account_get_id (account);
2625
2626         /* We need the TnyAccount provided by the
2627            account store because that is the one that
2628            knows the name of the Modest account */
2629         TnyAccount *modest_server_account =
2630                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2631                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2632                                                              server_acc_name);
2633         if (!modest_server_account) {
2634                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2635                 return;
2636         }
2637
2638         /* Update active account, but only if it's not a pseudo-account */
2639         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2640             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2641                 const gchar *modest_acc_name =
2642                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2643                 if (modest_acc_name)
2644                         modest_window_set_active_account (window, modest_acc_name);
2645         }
2646
2647         g_object_unref (modest_server_account);
2648 }
2649
2650 static void
2651 folder_refreshed_cb (ModestMailOperation *mail_op,
2652                      TnyFolder *folder,
2653                      gpointer user_data)
2654 {
2655         ModestMainWindow *win = NULL;
2656         GtkWidget *folder_view, *header_view;
2657         const GError *error;
2658
2659         g_return_if_fail (TNY_IS_FOLDER (folder));
2660
2661         win = MODEST_MAIN_WINDOW (user_data);
2662
2663         /* Check if the operation failed due to memory low conditions */
2664         error = modest_mail_operation_get_error (mail_op);
2665         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2666             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2667                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2668                                                         _KR("memr_ib_operation_disabled"),
2669                                                         TRUE);
2670                 return;
2671         }
2672
2673         folder_view =
2674                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2675         header_view =
2676                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2677
2678         if (folder_view) {
2679                 TnyFolderStore *current_folder;
2680
2681                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2682                 if (current_folder) {
2683                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2684                         g_object_unref (current_folder);
2685                         if (different)
2686                                 return;
2687                 }
2688         }
2689
2690         /* Check if folder is empty and set headers view contents style */
2691         if ((tny_folder_get_all_count (folder) == 0) ||
2692             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2693                 modest_main_window_set_contents_style (win,
2694                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2695 }
2696
2697 void
2698 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2699                                                TnyFolderStore *folder_store,
2700                                                gboolean selected,
2701                                                ModestMainWindow *main_window)
2702 {
2703         GtkWidget *header_view;
2704
2705         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2706
2707         header_view = modest_main_window_get_child_widget(main_window,
2708                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2709         if (!header_view)
2710                 return;
2711
2712
2713         if (TNY_IS_ACCOUNT (folder_store)) {
2714                 if (selected) {
2715                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2716
2717                         /* Show account details */
2718                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2719                 }
2720         } else {
2721                 if (TNY_IS_FOLDER (folder_store) && selected) {
2722                         TnyAccount *account;
2723
2724                         /* Update the active account */
2725                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2726                         if (account) {
2727                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2728                                 g_object_unref (account);
2729                                 account = NULL;
2730                         }
2731
2732                         /* Set the header style by default, it could
2733                            be changed later by the refresh callback to
2734                            empty */
2735                         modest_main_window_set_contents_style (main_window,
2736                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2737
2738                         /* Set folder on header view. This function
2739                            will call tny_folder_refresh_async so we
2740                            pass a callback that will be called when
2741                            finished. We use that callback to set the
2742                            empty view if there are no messages */
2743                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2744                                                        TNY_FOLDER (folder_store),
2745                                                        TRUE,
2746                                                        MODEST_WINDOW (main_window),
2747                                                        folder_refreshed_cb,
2748                                                        main_window);
2749
2750                         /* Restore configuration. We need to do this
2751                            *after* the set_folder because the widget
2752                            memory asks the header view about its
2753                            folder  */
2754                         modest_widget_memory_restore (modest_runtime_get_conf (),
2755                                                       G_OBJECT(header_view),
2756                                                       MODEST_CONF_HEADER_VIEW_KEY);
2757                 } else {
2758                         /* No need to save the header view
2759                            configuration for Maemo because it only
2760                            saves the sorting stuff and that it's
2761                            already being done by the sort
2762                            dialog. Remove it when the GNOME version
2763                            has the same behaviour */
2764 #ifdef MODEST_TOOLKIT_GTK
2765                         if (modest_main_window_get_contents_style (main_window) ==
2766                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2767                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2768                                                            G_OBJECT (header_view),
2769                                                            MODEST_CONF_HEADER_VIEW_KEY);
2770 #endif
2771                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2772                 }
2773         }
2774
2775         /* Update dimming state */
2776         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2777         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2778 }
2779 #endif
2780
2781 void
2782 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2783                                      ModestWindow *win)
2784 {
2785         GtkWidget *dialog;
2786         gchar *txt, *item;
2787         gboolean online;
2788
2789         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2790
2791         online = tny_device_is_online (modest_runtime_get_device());
2792
2793         if (online) {
2794                 /* already online -- the item is simply not there... */
2795                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2796                                                  GTK_DIALOG_MODAL,
2797                                                  GTK_MESSAGE_WARNING,
2798                                                  GTK_BUTTONS_NONE,
2799                                                  _("The %s you selected cannot be found"),
2800                                                  item);
2801                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2802                 gtk_dialog_run (GTK_DIALOG(dialog));
2803         } else {
2804                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2805                                                       GTK_WINDOW (win),
2806                                                       GTK_DIALOG_MODAL,
2807                                                       _("mcen_bd_dialog_cancel"),
2808                                                       GTK_RESPONSE_REJECT,
2809                                                       _("mcen_bd_dialog_ok"),
2810                                                       GTK_RESPONSE_ACCEPT,
2811                                                       NULL);
2812                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2813                                          "Do you want to get online?"), item);
2814                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2815                                     gtk_label_new (txt), FALSE, FALSE, 0);
2816                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2817                 g_free (txt);
2818
2819                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2820                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2821                         /* TODO: Comment about why is this commented out: */
2822                         /* modest_platform_connect_and_wait (); */
2823                 }
2824         }
2825         gtk_widget_destroy (dialog);
2826 }
2827
2828 void
2829 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2830                                      ModestWindow *win)
2831 {
2832         /* g_debug ("%s %s", __FUNCTION__, link); */
2833 }
2834
2835
2836 void
2837 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2838                                         ModestWindow *win)
2839 {
2840         modest_platform_activate_uri (link);
2841 }
2842
2843 void
2844 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2845                                           ModestWindow *win)
2846 {
2847         modest_platform_show_uri_popup (link);
2848 }
2849
2850 void
2851 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2852                                              ModestWindow *win)
2853 {
2854         /* we check for low-mem; in that case, show a warning, and don't allow
2855          * viewing attachments
2856          */
2857         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2858                 return;
2859
2860         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2861 }
2862
2863 void
2864 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2865                                           const gchar *address,
2866                                           ModestWindow *win)
2867 {
2868         /* g_debug ("%s %s", __FUNCTION__, address); */
2869 }
2870
2871 static void
2872 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2873                       TnyMsg *saved_draft,
2874                       gpointer user_data)
2875 {
2876         ModestMsgEditWindow *edit_window;
2877
2878         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2879 #ifndef MODEST_TOOLKIT_HILDON2
2880         ModestMainWindow *win;
2881
2882         /* FIXME. Make the header view sensitive again. This is a
2883          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2884          * for details */
2885         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2886                                          modest_runtime_get_window_mgr(), FALSE));
2887         if (win != NULL) {
2888                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2889                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2890                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2891         }
2892 #endif
2893
2894         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2895
2896         /* Set draft is there was no error */
2897         if (!modest_mail_operation_get_error (mail_op))
2898                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2899
2900         g_object_unref(edit_window);
2901 }
2902
2903 static gboolean
2904 enough_space_for_message (ModestMsgEditWindow *edit_window,
2905                           MsgData *data)
2906 {
2907         guint64 available_disk, expected_size;
2908         gint parts_count;
2909         guint64 parts_size;
2910
2911         /* Check size */
2912         available_disk = modest_utils_get_available_space (NULL);
2913         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2914         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2915                                                       data->html_body,
2916                                                       parts_count,
2917                                                       parts_size);
2918
2919         /* Double check: disk full condition or message too big */
2920         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2921             expected_size > available_disk) {
2922                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2923                 modest_platform_information_banner (NULL, NULL, msg);
2924                 g_free (msg);
2925
2926                 return FALSE;
2927         }
2928
2929         /*
2930          * djcb: if we're in low-memory state, we only allow for
2931          * saving messages smaller than
2932          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2933          * should still allow for sending anything critical...
2934          */
2935         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2936             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2937                 return FALSE;
2938
2939         /*
2940          * djcb: we also make sure that the attachments are smaller than the max size
2941          * this is for the case where we'd try to forward a message with attachments
2942          * bigger than our max allowed size, or sending an message from drafts which
2943          * somehow got past our checks when attaching.
2944          */
2945         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2946                 modest_platform_run_information_dialog (
2947                         GTK_WINDOW(edit_window),
2948                         _("mail_ib_error_attachment_size"),
2949                         TRUE);
2950                 return FALSE;
2951         }
2952
2953         return TRUE;
2954 }
2955
2956 gboolean
2957 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2958 {
2959         TnyTransportAccount *transport_account;
2960         ModestMailOperation *mail_operation;
2961         MsgData *data;
2962         gchar *account_name;
2963         ModestAccountMgr *account_mgr;
2964         gboolean had_error = FALSE;
2965
2966         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2967
2968         data = modest_msg_edit_window_get_msg_data (edit_window);
2969
2970         /* Check size */
2971         if (!enough_space_for_message (edit_window, data)) {
2972                 modest_msg_edit_window_free_msg_data (edit_window, data);
2973                 return FALSE;
2974         }
2975
2976         account_name = g_strdup (data->account_name);
2977         account_mgr = modest_runtime_get_account_mgr();
2978         if (!account_name)
2979                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2980         if (!account_name)
2981                 account_name = modest_account_mgr_get_default_account (account_mgr);
2982         if (!account_name) {
2983                 g_printerr ("modest: no account found\n");
2984                 modest_msg_edit_window_free_msg_data (edit_window, data);
2985                 return FALSE;
2986         }
2987
2988         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2989                 account_name = g_strdup (data->account_name);
2990         }
2991
2992         transport_account =
2993                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2994                                       (modest_runtime_get_account_store (),
2995                                        account_name,
2996                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2997         if (!transport_account) {
2998                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2999                 g_free (account_name);
3000                 modest_msg_edit_window_free_msg_data (edit_window, data);
3001                 return FALSE;
3002         }
3003
3004         /* Create the mail operation */
3005         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3006                                                                         NULL, NULL);
3007         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3008
3009         modest_mail_operation_save_to_drafts (mail_operation,
3010                                               transport_account,
3011                                               data->draft_msg,
3012                                               data->from,
3013                                               data->to, 
3014                                               data->cc, 
3015                                               data->bcc,
3016                                               data->subject,
3017                                               data->plain_body,
3018                                               data->html_body,
3019                                               data->attachments,
3020                                               data->images,
3021                                               data->priority_flags,
3022                                               data->references,
3023                                               data->in_reply_to,
3024                                               on_save_to_drafts_cb,
3025                                               g_object_ref(edit_window));
3026
3027 #ifdef MODEST_TOOLKIT_HILDON2
3028         /* In hildon2 we always show the information banner on saving to drafts.
3029          * It will be a system information banner in this case.
3030          */
3031         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3032         modest_platform_information_banner (NULL, NULL, text);
3033         g_free (text);
3034 #else
3035         ModestMainWindow *win = NULL;
3036
3037         /* Use the main window as the parent of the banner, if the
3038            main window does not exist it won't be shown, if the parent
3039            window exists then it's properly shown. We don't use the
3040            editor window because it could be closed (save to drafts
3041            could happen after closing the window */
3042         win = (ModestMainWindow *)
3043                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3044         if (win) {
3045                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3046                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3047                 g_free (text);
3048         }
3049 #endif
3050         modest_msg_edit_window_set_modified (edit_window, FALSE);
3051
3052         /* Frees */
3053         g_free (account_name);
3054         g_object_unref (G_OBJECT (transport_account));
3055         g_object_unref (G_OBJECT (mail_operation));
3056
3057         modest_msg_edit_window_free_msg_data (edit_window, data);
3058
3059 #ifndef MODEST_TOOLKIT_HILDON2
3060         /* ** FIXME **
3061          * If the drafts folder is selected then make the header view
3062          * insensitive while the message is being saved to drafts
3063          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3064          * is not very clean but it avoids letting the drafts folder
3065          * in an inconsistent state: the user could edit the message
3066          * being saved and undesirable things would happen.
3067          * In the average case the user won't notice anything at
3068          * all. In the worst case (the user is editing a really big
3069          * file from Drafts) the header view will be insensitive
3070          * during the saving process (10 or 20 seconds, depending on
3071          * the message). Anyway this is just a quick workaround: once
3072          * we find a better solution it should be removed
3073          * See NB#65125 (commend #18) for details.
3074          */
3075         if (!had_error && win != NULL) {
3076                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3077                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3078                 if (view != NULL) {
3079                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3080                         if (folder) {
3081                                 if (modest_tny_folder_is_local_folder(folder)) {
3082                                         TnyFolderType folder_type;
3083                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3084                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3085                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3086                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3087                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3088                                         }
3089                                 }
3090                         }
3091                         if (folder != NULL) g_object_unref(folder);
3092                 }
3093         }
3094 #endif
3095
3096         return !had_error;
3097 }
3098
3099 /* For instance, when clicking the Send toolbar button when editing a message: */
3100 gboolean
3101 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3102 {
3103         TnyTransportAccount *transport_account = NULL;
3104         gboolean had_error = FALSE;
3105         MsgData *data;
3106         ModestAccountMgr *account_mgr;
3107         gchar *account_name;
3108         ModestMailOperation *mail_operation;
3109         gchar *recipients;
3110
3111         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3112
3113         /* Check names but do not automatically add them to addressbook */
3114         if (!modest_msg_edit_window_check_names (edit_window, FALSE))
3115                 return TRUE;
3116
3117         data = modest_msg_edit_window_get_msg_data (edit_window);
3118
3119         recipients = g_strconcat (data->to?data->to:"", 
3120                                   data->cc?data->cc:"",
3121                                   data->bcc?data->bcc:"",
3122                                   NULL);
3123         if (recipients == NULL || recipients[0] == '\0') {
3124                 /* Empty subject -> no send */
3125                 g_free (recipients);
3126                 modest_msg_edit_window_free_msg_data (edit_window, data);
3127                 return FALSE;
3128         }
3129         g_free (recipients);
3130
3131         /* Check size */
3132         if (!enough_space_for_message (edit_window, data)) {
3133                 modest_msg_edit_window_free_msg_data (edit_window, data);
3134                 return FALSE;
3135         }
3136
3137         account_mgr = modest_runtime_get_account_mgr();
3138         account_name = g_strdup (data->account_name);
3139         if (!account_name)
3140                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3141
3142         if (!account_name)
3143                 account_name = modest_account_mgr_get_default_account (account_mgr);
3144
3145         if (!account_name) {
3146                 modest_msg_edit_window_free_msg_data (edit_window, data);
3147                 /* Run account setup wizard */
3148                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3149                         return TRUE;
3150                 }
3151         }
3152
3153         /* Get the currently-active transport account for this modest account: */
3154         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3155                 transport_account =
3156                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3157                                               (modest_runtime_get_account_store (),
3158                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3159         }
3160
3161         if (!transport_account) {
3162                 modest_msg_edit_window_free_msg_data (edit_window, data);
3163                 /* Run account setup wizard */
3164                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3165                         return TRUE;
3166         }
3167
3168
3169         /* Create the mail operation */
3170         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3171         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3172
3173         modest_mail_operation_send_new_mail (mail_operation,
3174                                              transport_account,
3175                                              data->draft_msg,
3176                                              data->from,
3177                                              data->to,
3178                                              data->cc,
3179                                              data->bcc,
3180                                              data->subject,
3181                                              data->plain_body,
3182                                              data->html_body,
3183                                              data->attachments,
3184                                              data->images,
3185                                              data->references,
3186                                              data->in_reply_to,
3187                                              data->priority_flags);
3188
3189         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3190                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3191
3192         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3193                 const GError *error = modest_mail_operation_get_error (mail_operation);
3194                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3195                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3196                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3197                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3198                         had_error = TRUE;
3199                 }
3200         }
3201
3202         /* Free data: */
3203         g_free (account_name);
3204         g_object_unref (G_OBJECT (transport_account));
3205         g_object_unref (G_OBJECT (mail_operation));
3206
3207         modest_msg_edit_window_free_msg_data (edit_window, data);
3208
3209         if (!had_error) {
3210                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3211
3212                 /* Save settings and close the window: */
3213                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3214         }
3215
3216         return !had_error;
3217 }
3218
3219 void
3220 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3221                                   ModestMsgEditWindow *window)
3222 {
3223         ModestMsgEditFormatState *format_state = NULL;
3224
3225         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3226         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3227
3228         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3229                 return;
3230
3231         format_state = modest_msg_edit_window_get_format_state (window);
3232         g_return_if_fail (format_state != NULL);
3233
3234         format_state->bold = gtk_toggle_action_get_active (action);
3235         modest_msg_edit_window_set_format_state (window, format_state);
3236         g_free (format_state);
3237
3238 }
3239
3240 void
3241 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3242                                      ModestMsgEditWindow *window)
3243 {
3244         ModestMsgEditFormatState *format_state = NULL;
3245
3246         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3247         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3248
3249         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3250                 return;
3251
3252         format_state = modest_msg_edit_window_get_format_state (window);
3253         g_return_if_fail (format_state != NULL);
3254
3255         format_state->italics = gtk_toggle_action_get_active (action);
3256         modest_msg_edit_window_set_format_state (window, format_state);
3257         g_free (format_state);
3258
3259 }
3260
3261 void
3262 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3263                                      ModestMsgEditWindow *window)
3264 {
3265         ModestMsgEditFormatState *format_state = NULL;
3266
3267         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3268         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3269
3270         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3271                 return;
3272
3273         format_state = modest_msg_edit_window_get_format_state (window);
3274         g_return_if_fail (format_state != NULL);
3275
3276         format_state->bullet = gtk_toggle_action_get_active (action);
3277         modest_msg_edit_window_set_format_state (window, format_state);
3278         g_free (format_state);
3279
3280 }
3281
3282 void
3283 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3284                                      GtkRadioAction *selected,
3285                                      ModestMsgEditWindow *window)
3286 {
3287         ModestMsgEditFormatState *format_state = NULL;
3288         GtkJustification value;
3289
3290         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3291
3292         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3293                 return;
3294
3295         value = gtk_radio_action_get_current_value (selected);
3296
3297         format_state = modest_msg_edit_window_get_format_state (window);
3298         g_return_if_fail (format_state != NULL);
3299
3300         format_state->justification = value;
3301         modest_msg_edit_window_set_format_state (window, format_state);
3302         g_free (format_state);
3303 }
3304
3305 void
3306 modest_ui_actions_on_select_editor_color (GtkAction *action,
3307                                           ModestMsgEditWindow *window)
3308 {
3309         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3310         g_return_if_fail (GTK_IS_ACTION (action));
3311
3312         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3313                 return;
3314
3315         modest_msg_edit_window_select_color (window);
3316 }
3317
3318 void
3319 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3320                                                      ModestMsgEditWindow *window)
3321 {
3322         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3323         g_return_if_fail (GTK_IS_ACTION (action));
3324
3325         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3326                 return;
3327
3328         modest_msg_edit_window_select_background_color (window);
3329 }
3330
3331 void
3332 modest_ui_actions_on_insert_image (GObject *object,
3333                                    ModestMsgEditWindow *window)
3334 {
3335         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3336
3337
3338         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3339                 return;
3340
3341         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3342                 return;
3343
3344         modest_msg_edit_window_insert_image (window);
3345 }
3346
3347 void
3348 modest_ui_actions_on_attach_file (GtkAction *action,
3349                                   ModestMsgEditWindow *window)
3350 {
3351         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3352         g_return_if_fail (GTK_IS_ACTION (action));
3353
3354         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3355                 return;
3356
3357         modest_msg_edit_window_offer_attach_file (window);
3358 }
3359
3360 void
3361 modest_ui_actions_on_remove_attachments (GtkAction *action,
3362                                          ModestMsgEditWindow *window)
3363 {
3364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3365
3366         modest_msg_edit_window_remove_attachments (window, NULL);
3367 }
3368
3369 static void
3370 do_create_folder_cb (ModestMailOperation *mail_op,
3371                      TnyFolderStore *parent_folder,
3372                      TnyFolder *new_folder,
3373                      gpointer user_data)
3374 {
3375         gchar *suggested_name = (gchar *) user_data;
3376         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3377         const GError *error;
3378
3379         error = modest_mail_operation_get_error (mail_op);
3380         if (error) {
3381                 gboolean disk_full = FALSE;
3382                 TnyAccount *account;
3383                 /* Show an error. If there was some problem writing to
3384                    disk, show it, otherwise show the generic folder
3385                    create error. We do it here and not in an error
3386                    handler because the call to do_create_folder will
3387                    stop the main loop in a gtk_dialog_run and then,
3388                    the message won't be shown until that dialog is
3389                    closed */
3390                 account = modest_mail_operation_get_account (mail_op);
3391                 if (account) {
3392                         disk_full =
3393                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3394                                                                                 (GtkWidget *) source_win,
3395                                                                                 (GError *) error,
3396                                                                                 account,
3397                                                                                 _("mail_in_ui_folder_create_error_memory"));
3398                         g_object_unref (account);
3399                 }
3400                 if (!disk_full) {
3401                         /* Show an error and try again if there is no
3402                            full memory condition */
3403                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3404                                                             _("mail_in_ui_folder_create_error"));
3405                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3406                 }
3407
3408         } else {
3409                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3410                  * FIXME: any other? */
3411                 GtkWidget *folder_view;
3412
3413 #ifndef MODEST_TOOLKIT_HILDON2
3414                 if (MODEST_IS_MAIN_WINDOW(source_win))
3415                         folder_view =
3416                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3417                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3418                 else
3419 #endif
3420                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3421                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3422
3423                 /* Select the newly created folder. It could happen
3424                    that the widget is no longer there (i.e. the window
3425                    has been destroyed, so we need to check this */
3426                 if (folder_view)
3427                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3428                                                           new_folder, FALSE);
3429                 g_object_unref (new_folder);
3430         }
3431         /* Free. Note that the first time it'll be NULL so noop */
3432         g_free (suggested_name);
3433         g_object_unref (source_win);
3434 }
3435
3436 typedef struct {
3437         gchar *folder_name;
3438         TnyFolderStore *parent;
3439 } CreateFolderConnect;
3440
3441 static void
3442 do_create_folder_performer (gboolean canceled,
3443                          GError *err,
3444                          GtkWindow *parent_window,
3445                          TnyAccount *account,
3446                          gpointer user_data)
3447 {
3448         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3449         ModestMailOperation *mail_op;
3450
3451         if (canceled || err) {
3452                 /* In disk full conditions we could get this error here */
3453                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3454                                                                 (GtkWidget *) parent_window, err,
3455                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3456
3457                 /* This happens if we have selected the outbox folder
3458                    as the parent */
3459                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3460                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3461                         /* Show an error and retry */
3462                         modest_platform_information_banner ((GtkWidget *) parent_window,
3463                                                             NULL,
3464                                                             _("mail_in_ui_folder_create_error"));
3465
3466                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3467                 }
3468
3469                 goto frees;
3470         }
3471
3472         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3473         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3474                                          mail_op);
3475         modest_mail_operation_create_folder (mail_op,
3476                                              helper->parent,
3477                                              (const gchar *) helper->folder_name,
3478                                              do_create_folder_cb,
3479                                              g_strdup (helper->folder_name));
3480         g_object_unref (mail_op);
3481
3482  frees:
3483         if (helper->parent)
3484                 g_object_unref (helper->parent);
3485         if (helper->folder_name)
3486                 g_free (helper->folder_name);
3487         g_slice_free (CreateFolderConnect, helper);
3488 }
3489
3490
3491 static void
3492 do_create_folder (GtkWindow *parent_window,
3493                   TnyFolderStore *suggested_parent,
3494                   const gchar *suggested_name)
3495 {
3496         gint result;
3497         gchar *folder_name = NULL;
3498         TnyFolderStore *parent_folder = NULL;
3499
3500         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3501                                                         suggested_parent,
3502                                                         (gchar *) suggested_name,
3503                                                         &folder_name,
3504                                                         &parent_folder);
3505
3506         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3507                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3508                 helper->folder_name = g_strdup (folder_name);
3509                 helper->parent = g_object_ref (parent_folder);
3510
3511                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3512                                                                TRUE,
3513                                                                parent_folder,
3514                                                                do_create_folder_performer,
3515                                                                helper);
3516         }
3517
3518         if (folder_name)
3519                 g_free (folder_name);
3520         if (parent_folder)
3521                 g_object_unref (parent_folder);
3522 }
3523
3524 static void
3525 modest_ui_actions_create_folder(GtkWidget *parent_window,
3526                                 GtkWidget *folder_view,
3527                                 TnyFolderStore *parent_folder)
3528 {
3529         if (!parent_folder) {
3530 #ifdef MODEST_TOOLKIT_HILDON2
3531                 ModestTnyAccountStore *acc_store;
3532
3533                 acc_store = modest_runtime_get_account_store ();
3534
3535                 parent_folder = (TnyFolderStore *)
3536                         modest_tny_account_store_get_local_folders_account (acc_store);
3537 #else
3538                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3539 #endif
3540         }
3541
3542         if (parent_folder) {
3543                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3544                 g_object_unref (parent_folder);
3545         }
3546 }
3547
3548 void
3549 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3550 {
3551
3552         g_return_if_fail (MODEST_IS_WINDOW(window));
3553
3554 #ifndef MODEST_TOOLKIT_HILDON2
3555         if (MODEST_IS_MAIN_WINDOW (window)) {
3556                 GtkWidget *folder_view;
3557
3558                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3559                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3560                 if (!folder_view)
3561                         return;
3562
3563                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3564 #else
3565         if (MODEST_IS_FOLDER_WINDOW (window)) {
3566                 GtkWidget *folder_view;
3567
3568                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3569                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3570 #endif
3571         } else {
3572                 g_assert_not_reached ();
3573         }
3574 }
3575
3576 static void
3577 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3578                                                gpointer user_data)
3579 {
3580         const GError *error = NULL;
3581         gchar *message = NULL;
3582         gboolean mem_full;
3583         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3584
3585         /* Get error message */
3586         error = modest_mail_operation_get_error (mail_op);
3587         if (!error)
3588                 g_return_if_reached ();
3589
3590         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3591                                                                 (GError *) error, account);
3592         if (mem_full) {
3593                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3594         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3595                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3596                 message = _CS("ckdg_ib_folder_already_exists");
3597         } else if (error->domain == TNY_ERROR_DOMAIN &&
3598                    error->code == TNY_SERVICE_ERROR_STATE) {
3599                 /* This means that the folder is already in use (a
3600                    message is opened for example */
3601                 message = _("emev_ni_internal_error");
3602         } else {
3603                 message = _CS("ckdg_ib_unable_to_rename");
3604         }
3605
3606         /* We don't set a parent for the dialog because the dialog
3607            will be destroyed so the banner won't appear */
3608         modest_platform_information_banner (NULL, NULL, message);
3609
3610         if (account)
3611                 g_object_unref (account);
3612         if (mem_full)
3613                 g_free (message);
3614 }
3615
3616 typedef struct {
3617         TnyFolderStore *folder;
3618         gchar *new_name;
3619 } RenameFolderInfo;
3620
3621 static void
3622 on_rename_folder_cb (ModestMailOperation *mail_op,
3623                      TnyFolder *new_folder,
3624                      gpointer user_data)
3625 {
3626         ModestFolderView *folder_view;
3627
3628         /* If the window was closed when renaming a folder, or if
3629          * it's not a main window this will happen */
3630         if (!MODEST_IS_FOLDER_VIEW (user_data))
3631                 return;
3632
3633         folder_view = MODEST_FOLDER_VIEW (user_data);
3634         /* Note that if the rename fails new_folder will be NULL */
3635         if (new_folder) {
3636                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3637 #ifndef MODEST_TOOLKIT_HILDON2
3638         } else {
3639                 modest_folder_view_select_first_inbox_or_local (folder_view);
3640 #endif
3641         }
3642         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3643 }
3644
3645 static void
3646 on_rename_folder_performer (gboolean canceled,
3647                             GError *err,
3648                             GtkWindow *parent_window,
3649                             TnyAccount *account,
3650                             gpointer user_data)
3651 {
3652         ModestMailOperation *mail_op = NULL;
3653         GtkTreeSelection *sel = NULL;
3654         GtkWidget *folder_view = NULL;
3655         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3656
3657         if (canceled || err) {
3658                 /* In disk full conditions we could get this error here */
3659                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3660                                                                 (GtkWidget *) parent_window, err,
3661                                                                 account, NULL);
3662         } else {
3663
3664                 mail_op =
3665                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3666                                         modest_ui_actions_rename_folder_error_handler,
3667                                         parent_window, NULL);
3668
3669                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3670                                 mail_op);
3671 #ifndef MODEST_TOOLKIT_HILDON2
3672                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3673
3674                         folder_view = modest_main_window_get_child_widget (
3675                                 MODEST_MAIN_WINDOW (parent_window),
3676                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3677                 }
3678 #else
3679                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3680                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3681                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3682                 }
3683 #endif
3684
3685                 /* Clear the folders view */
3686                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3687                 gtk_tree_selection_unselect_all (sel);
3688
3689                 /* Actually rename the folder */
3690                 modest_mail_operation_rename_folder (mail_op,
3691                                                      TNY_FOLDER (data->folder),
3692                                                      (const gchar *) (data->new_name),
3693                                                      on_rename_folder_cb,
3694                                                      folder_view);
3695                 g_object_unref (mail_op);
3696         }
3697
3698         g_object_unref (data->folder);
3699         g_free (data->new_name);
3700         g_free (data);
3701 }
3702
3703 void
3704 modest_ui_actions_on_rename_folder (GtkAction *action,
3705                                      ModestWindow *window)
3706 {
3707         modest_ui_actions_on_edit_mode_rename_folder (window);
3708 }
3709
3710 gboolean
3711 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3712 {
3713         TnyFolderStore *folder;
3714         GtkWidget *folder_view;
3715         gboolean do_rename = TRUE;
3716
3717         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3718
3719 #ifndef MODEST_TOOLKIT_HILDON2
3720         if (MODEST_IS_MAIN_WINDOW (window)) {
3721                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3722                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3723                 if (!folder_view)
3724                         return FALSE;
3725 #else
3726         if (MODEST_IS_FOLDER_WINDOW (window)) {
3727                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3728 #endif
3729         } else {
3730                 return FALSE;
3731         }
3732
3733         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3734
3735         if (!folder)
3736                 return FALSE;
3737
3738         if (TNY_IS_FOLDER (folder)) {
3739                 gchar *folder_name = NULL;
3740                 gint response;
3741                 const gchar *current_name;
3742                 TnyFolderStore *parent;
3743
3744                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3745                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3746                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3747                                                                      parent, current_name,
3748                                                                      &folder_name);
3749                 g_object_unref (parent);
3750
3751                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3752                         do_rename = FALSE;
3753                 } else {
3754                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3755                         rename_folder_data->folder = g_object_ref (folder);
3756                         rename_folder_data->new_name = folder_name;
3757                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3758                                         folder, on_rename_folder_performer, rename_folder_data);
3759                 }
3760         }
3761         g_object_unref (folder);
3762         return do_rename;
3763 }
3764
3765 static void
3766 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3767                                                gpointer user_data)
3768 {
3769         GObject *win = modest_mail_operation_get_source (mail_op);
3770
3771         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3772                                                 _("mail_in_ui_folder_delete_error"),
3773                                                 FALSE);
3774         g_object_unref (win);
3775 }
3776
3777 typedef struct {
3778         TnyFolderStore *folder;
3779         gboolean move_to_trash;
3780 } DeleteFolderInfo;
3781
3782 static void
3783 on_delete_folder_cb (gboolean canceled,
3784                   GError *err,
3785                   GtkWindow *parent_window,
3786                   TnyAccount *account,
3787                   gpointer user_data)
3788 {
3789         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3790         GtkWidget *folder_view;
3791         ModestMailOperation *mail_op;
3792         GtkTreeSelection *sel;
3793
3794         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3795                 /* Note that the connection process can fail due to
3796                    memory low conditions as it can not successfully
3797                    store the summary */
3798                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3799                                                                      (GtkWidget*) parent_window, err,
3800                                                                      account, NULL))
3801                         g_debug ("Error connecting when trying to delete a folder");
3802                 g_object_unref (G_OBJECT (info->folder));
3803                 g_free (info);
3804                 return;
3805         }
3806
3807 #ifndef MODEST_TOOLKIT_HILDON2
3808         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3809                 folder_view = modest_main_window_get_child_widget (
3810                         MODEST_MAIN_WINDOW (parent_window),
3811                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3812 #else
3813         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3814                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3815 #endif
3816         } else {
3817                 g_object_unref (G_OBJECT (info->folder));
3818                 g_free (info);
3819                 return;
3820         }
3821
3822         /* Unselect the folder before deleting it to free the headers */
3823         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3824         gtk_tree_selection_unselect_all (sel);
3825
3826         /* Create the mail operation */
3827         mail_op =
3828                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3829                                 modest_ui_actions_delete_folder_error_handler,
3830                                 NULL, NULL);
3831
3832         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3833                         mail_op);
3834         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3835
3836 #ifndef MODEST_TOOLKIT_HILDON2
3837         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3838 #endif
3839
3840         g_object_unref (mail_op);
3841         g_object_unref (info->folder);
3842         g_free (info);
3843 }
3844
3845 static gboolean
3846 delete_folder (ModestWindow *window, gboolean move_to_trash)
3847 {
3848         TnyFolderStore *folder;
3849         GtkWidget *folder_view;
3850         gint response;
3851         gchar *message;
3852
3853         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3854
3855 #ifndef MODEST_TOOLKIT_HILDON2
3856         if (MODEST_IS_MAIN_WINDOW (window)) {
3857
3858                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3859                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3860 #else
3861         if (MODEST_IS_FOLDER_WINDOW (window)) {
3862                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3863 #endif
3864         } else {
3865                 return FALSE;
3866         }
3867         if (!folder_view)
3868                 return FALSE;
3869
3870         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3871
3872         if (!folder)
3873                 return FALSE;
3874
3875         /* Show an error if it's an account */
3876         if (!TNY_IS_FOLDER (folder)) {
3877                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3878                                                         _("mail_in_ui_folder_delete_error"),
3879                                                         FALSE);
3880                 g_object_unref (G_OBJECT (folder));
3881                 return FALSE;
3882         }
3883
3884         /* Ask the user */
3885         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3886                                     tny_folder_get_name (TNY_FOLDER (folder)));
3887         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3888                                                             (const gchar *) message);
3889         g_free (message);
3890
3891         if (response == GTK_RESPONSE_OK) {
3892                 TnyAccount *account = NULL;
3893                 DeleteFolderInfo *info = NULL;
3894                 info = g_new0(DeleteFolderInfo, 1);
3895                 info->folder = g_object_ref (folder);
3896                 info->move_to_trash = move_to_trash;
3897
3898                 account = tny_folder_get_account (TNY_FOLDER (folder));
3899                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3900                                                                TRUE,
3901                                                                TNY_FOLDER_STORE (account),
3902                                                                on_delete_folder_cb, info);
3903                 g_object_unref (account);
3904                 g_object_unref (folder);
3905                 return TRUE;
3906         } else {
3907                 return FALSE;
3908         }
3909 }
3910
3911 void
3912 modest_ui_actions_on_delete_folder (GtkAction *action,
3913                                     ModestWindow *window)
3914 {
3915         modest_ui_actions_on_edit_mode_delete_folder (window);
3916 }
3917
3918 gboolean
3919 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3920 {
3921         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3922
3923         return delete_folder (window, FALSE);
3924 }
3925
3926 #ifndef MODEST_TOOLKIT_HILDON2
3927 void
3928 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3929 {
3930         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3931
3932         delete_folder (MODEST_WINDOW (main_window), TRUE);
3933 }
3934 #endif
3935
3936 typedef struct _PasswordDialogFields {
3937         GtkWidget *username;
3938         GtkWidget *password;
3939         GtkWidget *dialog;
3940 } PasswordDialogFields;
3941
3942 static void
3943 password_dialog_check_field (GtkEditable *editable,
3944                              PasswordDialogFields *fields)
3945 {
3946         const gchar *value;
3947         gboolean any_value_empty = FALSE;
3948
3949         value = modest_entry_get_text (fields->username);
3950         if ((value == NULL) || value[0] == '\0') {
3951                 any_value_empty = TRUE;
3952         }
3953         value = modest_entry_get_text (fields->password);
3954         if ((value == NULL) || value[0] == '\0') {
3955                 any_value_empty = TRUE;
3956         }
3957         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3958 }
3959
3960 void
3961 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3962                                          const gchar* server_account_name,
3963                                          gchar **username,
3964                                          gchar **password,
3965                                          gboolean *cancel,
3966                                          gboolean *remember,
3967                                          ModestMainWindow *main_window)
3968 {
3969         g_return_if_fail(server_account_name);
3970         gboolean completed = FALSE;
3971         PasswordDialogFields *fields = NULL;
3972
3973         /* Initalize output parameters: */
3974         if (cancel)
3975                 *cancel = FALSE;
3976
3977         if (remember)
3978                 *remember = TRUE;
3979
3980 #ifndef MODEST_TOOLKIT_GTK
3981         /* Maemo uses a different (awkward) button order,
3982          * It should probably just use gtk_alternative_dialog_button_order ().
3983          */
3984 #ifdef MODEST_TOOLKIT_HILDON2
3985         GtkWidget *dialog =
3986                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3987                                              NULL,
3988                                              GTK_DIALOG_MODAL,
3989                                              _HL("wdgt_bd_done"),
3990                                              GTK_RESPONSE_ACCEPT,
3991                                              NULL);
3992         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3993                                         HILDON_MARGIN_DOUBLE);
3994 #else
3995         GtkWidget *dialog =
3996                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3997                                              NULL,
3998                                              GTK_DIALOG_MODAL,
3999                                              _("mcen_bd_dialog_ok"),
4000                                              GTK_RESPONSE_ACCEPT,
4001                                              _("mcen_bd_dialog_cancel"),
4002                                              GTK_RESPONSE_REJECT,
4003                                              NULL);
4004 #endif /* MODEST_TOOLKIT_HILDON2 */
4005 #else
4006         GtkWidget *dialog =
4007                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4008                                              NULL,
4009                                              GTK_DIALOG_MODAL,
4010                                              GTK_STOCK_CANCEL,
4011                                              GTK_RESPONSE_REJECT,
4012                                              GTK_STOCK_OK,
4013                                              GTK_RESPONSE_ACCEPT,
4014                                              NULL);
4015 #endif /* MODEST_TOOLKIT_GTK */
4016
4017         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4018
4019         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4020                 modest_runtime_get_account_mgr(), server_account_name);
4021         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4022                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4023                 if (cancel)
4024                         *cancel = TRUE;
4025                 gtk_widget_destroy (dialog);
4026                 return;
4027         }
4028
4029         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4030         GtkWidget *label = gtk_label_new (txt);
4031         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4032         g_free (txt);
4033         g_free (server_name);
4034         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4035                             FALSE, FALSE, 0);
4036         server_name = NULL;
4037
4038         /* username: */
4039         gchar *initial_username = modest_account_mgr_get_server_account_username (
4040                 modest_runtime_get_account_mgr(), server_account_name);
4041
4042         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4043         if (initial_username)
4044                 modest_entry_set_text (entry_username, initial_username);
4045
4046         /* Dim this if a connection has ever succeeded with this username,
4047          * as per the UI spec: */
4048         /* const gboolean username_known =  */
4049         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4050         /*              modest_runtime_get_account_mgr(), server_account_name); */
4051         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4052
4053         /* We drop the username sensitive code and disallow changing it here
4054          * as tinymail does not support really changing the username in the callback
4055          */
4056         gtk_widget_set_sensitive (entry_username, FALSE);
4057
4058         /* Auto-capitalization is the default, so let's turn it off: */
4059 #ifdef MAEMO_CHANGES
4060         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4061 #endif
4062
4063         /* Create a size group to be used by all captions.
4064          * Note that HildonCaption does not create a default size group if we do not specify one.
4065          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4066         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4067
4068         GtkWidget *caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
4069                                                                     _("mail_fi_username"), FALSE,
4070                                                                     entry_username);
4071         gtk_widget_show (entry_username);
4072         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4073                 FALSE, FALSE, MODEST_MARGIN_HALF);
4074         gtk_widget_show (caption);
4075
4076         /* password: */
4077         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4078         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4079         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4080
4081         /* Auto-capitalization is the default, so let's turn it off: */
4082 #ifdef MAEMO_CHANGES
4083         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4084                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4085 #endif
4086
4087         caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
4088                                                          _("mail_fi_password"), FALSE,
4089                                                          entry_password);
4090         gtk_widget_show (entry_password);
4091         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4092                 FALSE, FALSE, MODEST_MARGIN_HALF);
4093         gtk_widget_show (caption);
4094         g_object_unref (sizegroup);
4095
4096         if (initial_username != NULL)
4097                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4098
4099 /* This is not in the Maemo UI spec:
4100         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4101         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4102                             TRUE, FALSE, 0);
4103 */
4104
4105         fields = g_slice_new0 (PasswordDialogFields);
4106         fields->username = entry_username;
4107         fields->password = entry_password;
4108         fields->dialog = dialog;
4109
4110         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4111         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4112         password_dialog_check_field (NULL, fields);
4113
4114         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4115
4116         while (!completed) {
4117
4118                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4119                         if (username) {
4120                                 *username = g_strdup (modest_entry_get_text (entry_username));
4121
4122                                 /* Note that an empty field becomes the "" string */
4123                                 if (*username && strlen (*username) > 0) {
4124                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4125                                                                                         server_account_name,
4126                                                                                         *username);
4127                                         completed = TRUE;
4128
4129                                         const gboolean username_was_changed =
4130                                                 (strcmp (*username, initial_username) != 0);
4131                                         if (username_was_changed) {
4132                                                 g_warning ("%s: tinymail does not yet support changing the "
4133                                                            "username in the get_password() callback.\n", __FUNCTION__);
4134                                         }
4135                                 } else {
4136                                         g_free (*username);
4137                                         *username = NULL;
4138                                         /* Show error */
4139                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4140                                                                             _("mcen_ib_username_pw_incorrect"));
4141                                         completed = FALSE;
4142                                 }
4143                         }
4144
4145                         if (password) {
4146                                 *password = g_strdup (modest_entry_get_text (entry_password));
4147
4148                                 /* We do not save the password in the configuration,
4149                                  * because this function is only called for passwords that should
4150                                  * not be remembered:
4151                                  modest_server_account_set_password (
4152                                  modest_runtime_get_account_mgr(), server_account_name,
4153                                  *password);
4154                                  */
4155                         }
4156                         if (cancel)
4157                                 *cancel   = FALSE;
4158                 } else {
4159 #ifndef MODEST_TOOLKIT_HILDON2
4160                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4161                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4162 #endif
4163                         completed = TRUE;
4164                         if (username)
4165                                 *username = NULL;
4166                         if (password)
4167                                 *password = NULL;
4168                         if (cancel)
4169                                 *cancel   = TRUE;
4170                 }
4171         }
4172
4173 /* This is not in the Maemo UI spec:
4174         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4175                 *remember = TRUE;
4176         else
4177                 *remember = FALSE;
4178 */
4179
4180         g_free (initial_username);
4181         gtk_widget_destroy (dialog);
4182         g_slice_free (PasswordDialogFields, fields);
4183
4184         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4185 }
4186
4187 void
4188 modest_ui_actions_on_cut (GtkAction *action,
4189                           ModestWindow *window)
4190 {
4191         GtkWidget *focused_widget;
4192         GtkClipboard *clipboard;
4193
4194         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4195         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4196         if (GTK_IS_EDITABLE (focused_widget)) {
4197                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4198                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4199                 gtk_clipboard_store (clipboard);
4200         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4201                 GtkTextBuffer *buffer;
4202
4203                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4204                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4205                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4206                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4207                         gtk_clipboard_store (clipboard);
4208                 }
4209         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4210                 TnyList *header_list = modest_header_view_get_selected_headers (
4211                                 MODEST_HEADER_VIEW (focused_widget));
4212                 gboolean continue_download = FALSE;
4213                 gint num_of_unc_msgs;
4214
4215                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4216
4217                 if (num_of_unc_msgs) {
4218                         TnyAccount *account = get_account_from_header_list (header_list);
4219                         if (account) {
4220                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4221                                 g_object_unref (account);
4222                         }
4223                 }
4224
4225                 if (num_of_unc_msgs == 0 || continue_download) {
4226 /*                      modest_platform_information_banner (
4227                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4228                         modest_header_view_cut_selection (
4229                                         MODEST_HEADER_VIEW (focused_widget));
4230                 }
4231
4232                 g_object_unref (header_list);
4233         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4234                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4235         }
4236 }
4237
4238 void
4239 modest_ui_actions_on_copy (GtkAction *action,
4240                            ModestWindow *window)
4241 {
4242         GtkClipboard *clipboard;
4243         GtkWidget *focused_widget;
4244         gboolean copied = TRUE;
4245
4246         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4247         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4248
4249         if (GTK_IS_LABEL (focused_widget)) {
4250                 gchar *selection;
4251                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4252                 gtk_clipboard_set_text (clipboard, selection, -1);
4253                 g_free (selection);
4254                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4255                 gtk_clipboard_store (clipboard);
4256         } else if (GTK_IS_EDITABLE (focused_widget)) {
4257                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4258                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4259                 gtk_clipboard_store (clipboard);
4260         } else if (GTK_IS_HTML (focused_widget)) {
4261                 const gchar *sel;
4262                 int len = -1;
4263                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4264                 if ((sel == NULL) || (sel[0] == '\0')) {
4265                         copied = FALSE;
4266                 } else {
4267                         gtk_html_copy (GTK_HTML (focused_widget));
4268                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4269                         gtk_clipboard_store (clipboard);
4270                 }
4271         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4272                 GtkTextBuffer *buffer;
4273                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4274                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4275                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4276                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4277                         gtk_clipboard_store (clipboard);
4278                 }
4279         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4280                 TnyList *header_list = modest_header_view_get_selected_headers (
4281                                 MODEST_HEADER_VIEW (focused_widget));
4282                 gboolean continue_download = FALSE;
4283                 gint num_of_unc_msgs;
4284
4285                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4286
4287                 if (num_of_unc_msgs) {
4288                         TnyAccount *account = get_account_from_header_list (header_list);
4289                         if (account) {
4290                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4291                                 g_object_unref (account);
4292                         }
4293                 }
4294
4295                 if (num_of_unc_msgs == 0 || continue_download) {
4296                         modest_platform_information_banner (
4297                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4298                         modest_header_view_copy_selection (
4299                                         MODEST_HEADER_VIEW (focused_widget));
4300                 } else
4301                         copied = FALSE;
4302
4303                 g_object_unref (header_list);
4304
4305         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4306                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4307         }
4308
4309         /* Show information banner if there was a copy to clipboard */
4310         if(copied)
4311                 modest_platform_information_banner (
4312                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4313 }
4314
4315 void
4316 modest_ui_actions_on_undo (GtkAction *action,
4317                            ModestWindow *window)
4318 {
4319         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4320                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4321 #ifndef MODEST_TOOLKIT_HILDON2
4322         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4323                 ModestEmailClipboard *clipboard = NULL;
4324                 /* Clear clipboard source */
4325                 clipboard = modest_runtime_get_email_clipboard ();
4326                 modest_email_clipboard_clear (clipboard);
4327 #endif
4328         } else {
4329                 g_return_if_reached ();
4330         }
4331 }
4332
4333 void
4334 modest_ui_actions_on_redo (GtkAction *action,
4335                            ModestWindow *window)
4336 {
4337         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4338                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4339         }
4340         else {
4341                 g_return_if_reached ();
4342         }
4343 }
4344
4345
4346 static void
4347 destroy_information_note (ModestMailOperation *mail_op,
4348                           gpointer user_data)
4349 {
4350         /* destroy information note */
4351         gtk_widget_destroy (GTK_WIDGET(user_data));
4352 }
4353
4354 static void
4355 destroy_folder_information_note (ModestMailOperation *mail_op,
4356                                  TnyFolder *new_folder,
4357                                  gpointer user_data)
4358 {
4359         /* destroy information note */
4360         gtk_widget_destroy (GTK_WIDGET(user_data));
4361 }
4362
4363
4364 static void
4365 paste_as_attachment_free (gpointer data)
4366 {
4367         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4368
4369         if (helper->banner) {
4370                 gtk_widget_destroy (helper->banner);
4371                 g_object_unref (helper->banner);
4372         }
4373         g_free (helper);
4374 }
4375
4376 static void
4377 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4378                             TnyHeader *header,
4379                             TnyMsg *msg,
4380                             gpointer userdata)
4381 {
4382         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4383         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4384
4385         if (msg == NULL)
4386                 return;
4387
4388         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4389
4390 }
4391
4392 void
4393 modest_ui_actions_on_paste (GtkAction *action,
4394                             ModestWindow *window)
4395 {
4396         GtkWidget *focused_widget = NULL;
4397         GtkWidget *inf_note = NULL;
4398         ModestMailOperation *mail_op = NULL;
4399
4400         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4401         if (GTK_IS_EDITABLE (focused_widget)) {
4402                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4403         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4404                 ModestEmailClipboard *e_clipboard = NULL;
4405                 e_clipboard = modest_runtime_get_email_clipboard ();
4406                 if (modest_email_clipboard_cleared (e_clipboard)) {
4407                         GtkTextBuffer *buffer;
4408                         GtkClipboard *clipboard;
4409
4410                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4411                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4412                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4413                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4414                         ModestMailOperation *mail_op;
4415                         TnyFolder *src_folder = NULL;
4416                         TnyList *data = NULL;
4417                         gboolean delete;
4418                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4419                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4420                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4421                                                                            _CS("ckct_nw_pasting"));
4422                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4423                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4424                         if (helper->banner != NULL) {
4425                                 g_object_ref (G_OBJECT (helper->banner));
4426                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4427                         }
4428
4429                         if (data != NULL) {
4430                                 modest_mail_operation_get_msgs_full (mail_op,
4431                                                                      data,
4432                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4433                                                                      helper,
4434                                                                      paste_as_attachment_free);
4435                         }
4436                         /* Free */
4437                         if (data)
4438                                 g_object_unref (data);
4439                         if (src_folder)
4440                                 g_object_unref (src_folder);
4441
4442                 }
4443         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4444                 ModestEmailClipboard *clipboard = NULL;
4445                 TnyFolder *src_folder = NULL;
4446                 TnyFolderStore *folder_store = NULL;
4447                 TnyList *data = NULL;
4448                 gboolean delete = FALSE;
4449
4450                 /* Check clipboard source */
4451                 clipboard = modest_runtime_get_email_clipboard ();
4452                 if (modest_email_clipboard_cleared (clipboard))
4453                         return;
4454
4455                 /* Get elements to paste */
4456                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4457
4458                 /* Create a new mail operation */
4459                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4460
4461                 /* Get destination folder */
4462                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4463
4464                 /* transfer messages  */
4465                 if (data != NULL) {
4466                         gint response = 0;
4467
4468                         /* Ask for user confirmation */
4469                         response =
4470                                 modest_ui_actions_msgs_move_to_confirmation (window,
4471                                                                              TNY_FOLDER (folder_store),
4472                                                                              delete,
4473                                                                              data);
4474
4475                         if (response == GTK_RESPONSE_OK) {
4476                                 /* Launch notification */
4477                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4478                                                                              _CS("ckct_nw_pasting"));
4479                                 if (inf_note != NULL)  {
4480                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4481                                         gtk_widget_show (GTK_WIDGET(inf_note));
4482                                 }
4483
4484                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4485                                 modest_mail_operation_xfer_msgs (mail_op,
4486                                                                  data,
4487                                                                  TNY_FOLDER (folder_store),
4488                                                                  delete,
4489                                                                  destroy_information_note,
4490                                                                  inf_note);
4491                         } else {
4492                                 g_object_unref (mail_op);
4493                         }
4494
4495                 } else if (src_folder != NULL) {
4496                         /* Launch notification */
4497                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4498                                                                      _CS("ckct_nw_pasting"));
4499                         if (inf_note != NULL)  {
4500                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4501                                 gtk_widget_show (GTK_WIDGET(inf_note));
4502                         }
4503
4504                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4505                         modest_mail_operation_xfer_folder (mail_op,
4506                                                            src_folder,
4507                                                            folder_store,
4508                                                            delete,
4509                                                            destroy_folder_information_note,
4510                                                            inf_note);
4511                 }
4512
4513                 /* Free */
4514                 if (data != NULL)
4515                         g_object_unref (data);
4516                 if (src_folder != NULL)
4517                         g_object_unref (src_folder);
4518                 if (folder_store != NULL)
4519                         g_object_unref (folder_store);
4520         }
4521 }
4522
4523
4524 void
4525 modest_ui_actions_on_select_all (GtkAction *action,
4526                                  ModestWindow *window)
4527 {
4528         GtkWidget *focused_widget;
4529
4530         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4531         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4532                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4533         } else if (GTK_IS_LABEL (focused_widget)) {
4534                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4535         } else if (GTK_IS_EDITABLE (focused_widget)) {
4536                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4537         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4538                 GtkTextBuffer *buffer;
4539                 GtkTextIter start, end;
4540
4541                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4542                 gtk_text_buffer_get_start_iter (buffer, &start);
4543                 gtk_text_buffer_get_end_iter (buffer, &end);
4544                 gtk_text_buffer_select_range (buffer, &start, &end);
4545         } else if (GTK_IS_HTML (focused_widget)) {
4546                 gtk_html_select_all (GTK_HTML (focused_widget));
4547 #ifndef MODEST_TOOLKIT_HILDON2
4548         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4549                 GtkWidget *header_view = focused_widget;
4550                 GtkTreeSelection *selection = NULL;
4551
4552                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4553                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4554                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4555                 }
4556
4557                 /* Disable window dimming management */
4558                 modest_window_disable_dimming (MODEST_WINDOW(window));
4559
4560                 /* Select all messages */
4561                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4562                 gtk_tree_selection_select_all (selection);
4563
4564                 /* Set focuse on header view */
4565                 gtk_widget_grab_focus (header_view);
4566
4567                 /* Enable window dimming management */
4568                 modest_window_enable_dimming (MODEST_WINDOW(window));
4569                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4570                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4571 #endif
4572         }
4573
4574 }
4575
4576 void
4577 modest_ui_actions_on_mark_as_read (GtkAction *action,
4578                                    ModestWindow *window)
4579 {
4580         g_return_if_fail (MODEST_IS_WINDOW(window));
4581
4582         /* Mark each header as read */
4583         do_headers_action (window, headers_action_mark_as_read, NULL);
4584 }
4585
4586 void
4587 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4588                                      ModestWindow *window)
4589 {
4590         g_return_if_fail (MODEST_IS_WINDOW(window));
4591
4592         /* Mark each header as read */
4593         do_headers_action (window, headers_action_mark_as_unread, NULL);
4594 }
4595
4596 void
4597 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4598                                   GtkRadioAction *selected,
4599                                   ModestWindow *window)
4600 {
4601         gint value;
4602
4603         value = gtk_radio_action_get_current_value (selected);
4604         if (MODEST_IS_WINDOW (window)) {
4605                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4606         }
4607 }
4608
4609 void
4610 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4611                                                GtkRadioAction *selected,
4612                                                ModestWindow *window)
4613 {
4614         TnyHeaderFlags flags;
4615         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4616
4617         flags = gtk_radio_action_get_current_value (selected);
4618         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4619 }
4620
4621 void
4622 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4623                                                   GtkRadioAction *selected,
4624                                                   ModestWindow *window)
4625 {
4626         gint file_format;
4627
4628         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4629
4630         file_format = gtk_radio_action_get_current_value (selected);
4631         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4632 }
4633
4634
4635 void
4636 modest_ui_actions_on_zoom_plus (GtkAction *action,
4637                                 ModestWindow *window)
4638 {
4639         g_return_if_fail (MODEST_IS_WINDOW (window));
4640
4641         modest_window_zoom_plus (MODEST_WINDOW (window));
4642 }
4643
4644 void
4645 modest_ui_actions_on_zoom_minus (GtkAction *action,
4646                                  ModestWindow *window)
4647 {
4648         g_return_if_fail (MODEST_IS_WINDOW (window));
4649
4650         modest_window_zoom_minus (MODEST_WINDOW (window));
4651 }
4652
4653 void
4654 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4655                                            ModestWindow *window)
4656 {
4657         ModestWindowMgr *mgr;
4658         gboolean fullscreen, active;
4659         g_return_if_fail (MODEST_IS_WINDOW (window));
4660
4661         mgr = modest_runtime_get_window_mgr ();
4662
4663         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4664         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4665
4666         if (active != fullscreen) {
4667                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4668 #ifndef MODEST_TOOLKIT_HILDON2
4669                 gtk_window_present (GTK_WINDOW (window));
4670 #endif
4671         }
4672 }
4673
4674 void
4675 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4676                                         ModestWindow *window)
4677 {
4678         ModestWindowMgr *mgr;
4679         gboolean fullscreen;
4680
4681         g_return_if_fail (MODEST_IS_WINDOW (window));
4682
4683         mgr = modest_runtime_get_window_mgr ();
4684         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4685         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4686
4687 #ifndef MODEST_TOOLKIT_HILDON2
4688         gtk_window_present (GTK_WINDOW (window));
4689 #endif
4690 }
4691
4692 /*
4693  * Used by modest_ui_actions_on_details to call do_headers_action
4694  */
4695 static void
4696 headers_action_show_details (TnyHeader *header,
4697                              ModestWindow *window,
4698                              gpointer user_data)
4699
4700 {
4701         gboolean async_retrieval;
4702         TnyMsg *msg = NULL;
4703
4704         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4705                 async_retrieval = TRUE;
4706                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4707         } else {
4708                 async_retrieval = FALSE;
4709         }
4710         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4711         if (msg)
4712                 g_object_unref (msg);
4713 }
4714
4715 /*
4716  * Show the header details in a ModestDetailsDialog widget
4717  */
4718 void
4719 modest_ui_actions_on_details (GtkAction *action,
4720                               ModestWindow *win)
4721 {
4722         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4723                 TnyMsg *msg;
4724                 TnyHeader *header;
4725
4726                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4727                 if (!msg)
4728                         return;
4729
4730                 header = tny_msg_get_header (msg);
4731                 if (header) {
4732                         headers_action_show_details (header, win, NULL);
4733                         g_object_unref (header);
4734                 }
4735                 g_object_unref (msg);
4736 #ifndef MODEST_TOOLKIT_HILDON2
4737         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4738                 GtkWidget *folder_view, *header_view;
4739
4740                 /* Check which widget has the focus */
4741                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4742                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4743                 if (gtk_widget_is_focus (folder_view)) {
4744                         TnyFolderStore *folder_store
4745                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4746                         if (!folder_store) {
4747                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4748                                 return;
4749                         }
4750                         /* Show only when it's a folder */
4751                         /* This function should not be called for account items,
4752                          * because we dim the menu item for them. */
4753                         if (TNY_IS_FOLDER (folder_store)) {
4754                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4755                                                                            TNY_FOLDER (folder_store));
4756                         }
4757
4758                         g_object_unref (folder_store);
4759
4760                 } else {
4761                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4762                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4763                         /* Show details of each header */
4764                         do_headers_action (win, headers_action_show_details, header_view);
4765                 }
4766 #else
4767         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4768                 TnyFolder *folder;
4769                 GtkWidget *header_view;
4770
4771                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4772                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4773                 if (folder) {
4774                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4775                                                                    folder);
4776                         g_object_unref (folder);
4777                 }
4778 #endif
4779         }
4780 }
4781
4782 void
4783 modest_ui_actions_on_limit_error (GtkAction *action,
4784                                   ModestWindow *win)
4785 {
4786         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4787
4788         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4789
4790 }
4791
4792 void
4793 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4794                                      ModestMsgEditWindow *window)
4795 {
4796         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4797
4798         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4799 }
4800
4801 void
4802 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4803                                       ModestMsgEditWindow *window)
4804 {
4805         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4806
4807         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4808 }
4809
4810 #ifndef MODEST_TOOLKIT_HILDON2
4811 void
4812 modest_ui_actions_toggle_folders_view (GtkAction *action,
4813                                        ModestMainWindow *main_window)
4814 {
4815         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4816
4817         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4818                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4819         else
4820                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4821 }
4822 #endif
4823
4824 void
4825 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4826                                      ModestWindow *window)
4827 {
4828         gboolean active, fullscreen = FALSE;
4829         ModestWindowMgr *mgr;
4830
4831         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4832
4833         /* Check if we want to toggle the toolbar view in fullscreen
4834            or normal mode */
4835         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4836                      "ViewShowToolbarFullScreen")) {
4837                 fullscreen = TRUE;
4838         }
4839
4840         /* Toggle toolbar */
4841         mgr = modest_runtime_get_window_mgr ();
4842         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4843 }
4844
4845 void
4846 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4847                                            ModestMsgEditWindow *window)
4848 {
4849         modest_msg_edit_window_select_font (window);
4850 }
4851
4852
4853 void
4854 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4855                                                   const gchar *display_name,
4856                                                   GtkWindow *window)
4857 {
4858         /* don't update the display name if it was already set;
4859          * updating the display name apparently is expensive */
4860         const gchar* old_name = gtk_window_get_title (window);
4861
4862         if (display_name == NULL)
4863                 display_name = " ";
4864
4865         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4866                 return; /* don't do anything */
4867
4868         /* This is usually used to change the title of the main window, which
4869          * is the one that holds the folder view. Note that this change can
4870          * happen even when the widget doesn't have the focus. */
4871         gtk_window_set_title (window, display_name);
4872
4873 }
4874
4875 void
4876 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4877 {
4878         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4879         modest_msg_edit_window_select_contacts (window);
4880 }
4881
4882 void
4883 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4884 {
4885         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4886         modest_msg_edit_window_check_names (window, FALSE);
4887 }
4888
4889 #ifndef MODEST_TOOLKIT_HILDON2
4890 /*
4891  * This function is used to track changes in the selection of the
4892  * folder view that is inside the "move to" dialog to enable/disable
4893  * the OK button because we do not want the user to select a disallowed
4894  * destination for a folder.
4895  * The user also not desired to be able to use NEW button on items where
4896  * folder creation is not possibel.
4897  */
4898 static void
4899 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4900                                             TnyFolderStore *folder_store,
4901                                             gboolean selected,
4902                                             gpointer user_data)
4903 {
4904         GtkWidget *dialog = NULL;
4905         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4906         gboolean moving_folder = FALSE;
4907         gboolean is_local_account = TRUE;
4908         GtkWidget *folder_view = NULL;
4909         ModestTnyFolderRules rules;
4910
4911         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4912
4913         if (!selected)
4914                 return;
4915
4916         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4917         if (!dialog)
4918                 return;
4919
4920         /* check if folder_store is an remote account */
4921         if (TNY_IS_ACCOUNT (folder_store)) {
4922                 TnyAccount *local_account = NULL;
4923                 TnyAccount *mmc_account = NULL;
4924                 ModestTnyAccountStore *account_store = NULL;
4925
4926                 account_store = modest_runtime_get_account_store ();
4927                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4928                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4929
4930                 if ((gpointer) local_account != (gpointer) folder_store &&
4931                     (gpointer) mmc_account != (gpointer) folder_store) {
4932                         ModestProtocolType proto;
4933                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4934                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4935                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4936                         }
4937                         is_local_account = FALSE;
4938                         /* New button should be dimmed on remote
4939                            POP account root */
4940                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4941                                                                                          proto,
4942                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4943                 }
4944                 g_object_unref (local_account);
4945
4946                 /* It could not exist */
4947                 if (mmc_account)
4948                         g_object_unref (mmc_account);
4949         }
4950
4951         /* Check the target folder rules */
4952         if (TNY_IS_FOLDER (folder_store)) {
4953                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4954                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4955                         ok_sensitive = FALSE;
4956                         new_sensitive = FALSE;
4957                         goto end;
4958                 }
4959         }
4960
4961         /* Check if we're moving a folder */
4962         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4963                 /* Get the widgets */
4964                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4965                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4966                 if (gtk_widget_is_focus (folder_view))
4967                         moving_folder = TRUE;
4968         }
4969
4970         if (moving_folder) {
4971                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4972
4973                 /* Get the folder to move */
4974                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4975
4976                 /* Check that we're not moving to the same folder */
4977                 if (TNY_IS_FOLDER (moved_folder)) {
4978                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4979                         if (parent == folder_store)
4980                                 ok_sensitive = FALSE;
4981                         g_object_unref (parent);
4982                 }
4983
4984                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4985                         /* Do not allow to move to an account unless it's the
4986                            local folders account */
4987                         if (!is_local_account)
4988                                 ok_sensitive = FALSE;
4989                 }
4990
4991                 if (ok_sensitive && (moved_folder == folder_store)) {
4992                         /* Do not allow to move to itself */
4993                         ok_sensitive = FALSE;
4994                 }
4995                 g_object_unref (moved_folder);
4996         } else {
4997                 TnyFolder *src_folder = NULL;
4998
4999                 /* Moving a message */
5000                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5001
5002                         TnyHeader *header = NULL;
5003                         header = modest_msg_view_window_get_header
5004                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5005                         if (!TNY_IS_HEADER(header))
5006                                 g_warning ("%s: could not get source header", __FUNCTION__);
5007                         else
5008                                 src_folder = tny_header_get_folder (header);
5009
5010                         if (header)
5011                                 g_object_unref (header);
5012                 } else {
5013                         src_folder =
5014                                 TNY_FOLDER (modest_folder_view_get_selected
5015                                             (MODEST_FOLDER_VIEW (folder_view)));
5016                 }
5017
5018                 if (TNY_IS_FOLDER(src_folder)) {
5019                         /* Do not allow to move the msg to the same folder */
5020                         /* Do not allow to move the msg to an account */
5021                         if ((gpointer) src_folder == (gpointer) folder_store ||
5022                             TNY_IS_ACCOUNT (folder_store))
5023                                 ok_sensitive = FALSE;
5024                         g_object_unref (src_folder);
5025                 } else
5026                         g_warning ("%s: could not get source folder", __FUNCTION__);
5027         }
5028
5029  end:
5030         /* Set sensitivity of the OK and NEW button */
5031         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5032         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5033 }
5034 #endif
5035
5036 static void
5037 on_move_to_dialog_response (GtkDialog *dialog,
5038                             gint       response,
5039                             gpointer   user_data)
5040 {
5041         GtkWidget *parent_win;
5042         MoveToInfo *helper = NULL;
5043         ModestFolderView *folder_view;
5044         gboolean unset_edit_mode = FALSE;
5045
5046         helper = (MoveToInfo *) user_data;
5047
5048         parent_win = (GtkWidget *) helper->win;
5049         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5050                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5051         switch (response) {
5052                 TnyFolderStore *dst_folder;
5053                 TnyFolderStore *selected;
5054
5055         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5056                 selected = modest_folder_view_get_selected (folder_view);
5057                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5058                 g_object_unref (selected);
5059                 return;
5060         case GTK_RESPONSE_NONE:
5061         case GTK_RESPONSE_CANCEL:
5062         case GTK_RESPONSE_DELETE_EVENT:
5063                 break;
5064         case GTK_RESPONSE_OK:
5065                 dst_folder = modest_folder_view_get_selected (folder_view);
5066
5067 #ifndef MODEST_TOOLKIT_HILDON2
5068                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5069                         /* Clean list to move used for filtering */
5070                         modest_folder_view_set_list_to_move (folder_view, NULL);
5071
5072                         modest_ui_actions_on_main_window_move_to (NULL,
5073                                                                   GTK_WIDGET (folder_view),
5074                                                                   dst_folder,
5075                                                                   MODEST_MAIN_WINDOW (parent_win));
5076 #else
5077                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5078                         /* Clean list to move used for filtering */
5079                         modest_folder_view_set_list_to_move (folder_view, NULL);
5080
5081                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5082                                                                     dst_folder,
5083                                                                     helper->list,
5084                                                                     GTK_WINDOW (parent_win));
5085 #endif
5086                 } else {
5087                         /* if the user selected a root folder
5088                            (account) then do not perform any action */
5089                         if (TNY_IS_ACCOUNT (dst_folder)) {
5090                                 g_signal_stop_emission_by_name (dialog, "response");
5091                                 return;
5092                         }
5093
5094                         /* Clean list to move used for filtering */
5095                         modest_folder_view_set_list_to_move (folder_view, NULL);
5096
5097                         /* Moving from headers window in edit mode */
5098                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5099                                                              dst_folder,
5100                                                              MODEST_WINDOW (parent_win));
5101                 }
5102
5103                 if (dst_folder)
5104                         g_object_unref (dst_folder);
5105
5106                 unset_edit_mode = TRUE;
5107                 break;
5108         default:
5109                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5110         }
5111
5112         /* Free the helper and exit */
5113         if (helper->list)
5114                 g_object_unref (helper->list);
5115         if (unset_edit_mode) {
5116 #ifdef MODEST_TOOLKIT_HILDON2
5117                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5118 #endif
5119         }
5120         g_slice_free (MoveToInfo, helper);
5121         gtk_widget_destroy (GTK_WIDGET (dialog));
5122 }
5123
5124 static GtkWidget*
5125 create_move_to_dialog (GtkWindow *win,
5126                        GtkWidget *folder_view,
5127                        TnyList *list_to_move)
5128 {
5129         GtkWidget *dialog, *tree_view = NULL;
5130
5131         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5132
5133 #ifndef MODEST_TOOLKIT_HILDON2
5134         /* Track changes in the selection to
5135          * disable the OK button whenever "Move to" is not possible
5136          * disbale NEW button whenever New is not possible */
5137         g_signal_connect (tree_view,
5138                           "folder_selection_changed",
5139                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5140                           win);
5141 #endif
5142
5143         /* It could happen that we're trying to move a message from a
5144            window (msg window for example) after the main window was
5145            closed, so we can not just get the model of the folder
5146            view */
5147         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5148                 const gchar *visible_id = NULL;
5149
5150                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5151                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5152                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5153                                                MODEST_FOLDER_VIEW(tree_view));
5154
5155                 visible_id =
5156                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5157
5158                 /* Show the same account than the one that is shown in the main window */
5159                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5160                                                                              visible_id);
5161         } else {
5162                 const gchar *active_account_name = NULL;
5163                 ModestAccountMgr *mgr = NULL;
5164                 ModestAccountSettings *settings = NULL;
5165                 ModestServerAccountSettings *store_settings = NULL;
5166
5167                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5168                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5169                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5170                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5171
5172                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5173                 mgr = modest_runtime_get_account_mgr ();
5174                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5175
5176                 if (settings) {
5177                         const gchar *store_account_name;
5178                         store_settings = modest_account_settings_get_store_settings (settings);
5179                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5180
5181                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5182                                                                                      store_account_name);
5183                         g_object_unref (store_settings);
5184                         g_object_unref (settings);
5185                 }
5186         }
5187
5188         /* we keep a pointer to the embedded folder view, so we can
5189          *   retrieve it with get_folder_view_from_move_to_dialog (see
5190          *   above) later (needed for focus handling)
5191          */
5192         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5193
5194         /* Hide special folders */
5195 #ifndef MODEST_TOOLKIT_HILDON2
5196         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5197 #endif
5198         if (list_to_move)
5199                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5200 #ifndef MODEST_TOOLKIT_HILDON2
5201         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5202 #endif
5203
5204         gtk_widget_show (GTK_WIDGET (tree_view));
5205
5206         return dialog;
5207 }
5208
5209 /*
5210  * Shows a confirmation dialog to the user when we're moving messages
5211  * from a remote server to the local storage. Returns the dialog
5212  * response. If it's other kind of movement then it always returns
5213  * GTK_RESPONSE_OK
5214  *
5215  * This one is used by the next functions:
5216  *      modest_ui_actions_on_paste                      - commented out
5217  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5218  */
5219 gint
5220 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5221                                              TnyFolder *dest_folder,
5222                                              gboolean delete,
5223                                              TnyList *headers)
5224 {
5225         gint response = GTK_RESPONSE_OK;
5226         TnyAccount *account = NULL;
5227         TnyFolder *src_folder = NULL;
5228         TnyIterator *iter = NULL;
5229         TnyHeader *header = NULL;
5230
5231         /* return with OK if the destination is a remote folder */
5232         if (modest_tny_folder_is_remote_folder (dest_folder))
5233                 return GTK_RESPONSE_OK;
5234
5235         /* Get source folder */
5236         iter = tny_list_create_iterator (headers);
5237         header = TNY_HEADER (tny_iterator_get_current (iter));
5238         if (header) {
5239                 src_folder = tny_header_get_folder (header);
5240                 g_object_unref (header);
5241         }
5242         g_object_unref (iter);
5243
5244         /* if no src_folder, message may be an attahcment */
5245         if (src_folder == NULL)
5246                 return GTK_RESPONSE_CANCEL;
5247
5248         /* If the source is a local or MMC folder */
5249         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5250                 g_object_unref (src_folder);
5251                 return GTK_RESPONSE_OK;
5252         }
5253
5254         /* Get the account */
5255         account = tny_folder_get_account (src_folder);
5256
5257         /* now if offline we ask the user */
5258         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5259                 response = GTK_RESPONSE_OK;
5260         else
5261                 response = GTK_RESPONSE_CANCEL;
5262
5263         /* Frees */
5264         g_object_unref (src_folder);
5265         g_object_unref (account);
5266
5267         return response;
5268 }
5269
5270 static void
5271 move_to_helper_destroyer (gpointer user_data)
5272 {
5273         MoveToHelper *helper = (MoveToHelper *) user_data;
5274
5275         /* Close the "Pasting" information banner */
5276         if (helper->banner) {
5277                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5278                 g_object_unref (helper->banner);
5279         }
5280         if (gtk_tree_row_reference_valid (helper->reference)) {
5281                 gtk_tree_row_reference_free (helper->reference);
5282                 helper->reference = NULL;
5283         }
5284         g_free (helper);
5285 }
5286
5287 static void
5288 move_to_cb (ModestMailOperation *mail_op,
5289             gpointer user_data)
5290 {
5291         MoveToHelper *helper = (MoveToHelper *) user_data;
5292         GObject *object = modest_mail_operation_get_source (mail_op);
5293
5294         /* Note that the operation could have failed, in that case do
5295            nothing */
5296         if (modest_mail_operation_get_status (mail_op) !=
5297             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5298                 goto frees;
5299
5300         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5301                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5302
5303                 if (!modest_msg_view_window_select_next_message (self) &&
5304                     !modest_msg_view_window_select_previous_message (self)) {
5305                         /* No more messages to view, so close this window */
5306                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5307                 }
5308 #ifndef MODEST_TOOLKIT_HILDON2
5309         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5310                    gtk_tree_row_reference_valid (helper->reference)) {
5311                 GtkWidget *header_view;
5312                 GtkTreePath *path;
5313                 GtkTreeSelection *sel;
5314
5315                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5316                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5317                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5318                 path = gtk_tree_row_reference_get_path (helper->reference);
5319                 /* We need to unselect the previous one
5320                    because we could be copying instead of
5321                    moving */
5322                 gtk_tree_selection_unselect_all (sel);
5323                 gtk_tree_selection_select_path (sel, path);
5324                 gtk_tree_path_free (path);
5325 #endif
5326         }
5327         g_object_unref (object);
5328
5329  frees:
5330         /* Destroy the helper */
5331         move_to_helper_destroyer (helper);
5332 }
5333
5334 static void
5335 folder_move_to_cb (ModestMailOperation *mail_op,
5336                    TnyFolder *new_folder,
5337                    gpointer user_data)
5338 {
5339         GObject *object;
5340
5341         object = modest_mail_operation_get_source (mail_op);
5342 #ifndef MODEST_TOOLKIT_HILDON2
5343         if (MODEST_IS_MAIN_WINDOW (object)) {
5344                 GtkWidget *folder_view;
5345                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5346                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5347                 g_object_ref (folder_view);
5348                 g_object_unref (object);
5349                 move_to_cb (mail_op, user_data);
5350                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5351                 g_object_unref (folder_view);
5352         } else {
5353 #else
5354                 {
5355 #endif
5356                 move_to_cb (mail_op, user_data);
5357         }
5358 }
5359
5360 static void
5361 msgs_move_to_cb (ModestMailOperation *mail_op,
5362                  gpointer user_data)
5363 {
5364         move_to_cb (mail_op, user_data);
5365 }
5366
5367 void
5368 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5369                                              gpointer user_data)
5370 {
5371         GObject *win = NULL;
5372         const GError *error;
5373         TnyAccount *account = NULL;
5374
5375 #ifndef MODEST_TOOLKIT_HILDON2
5376         ModestWindow *main_window = NULL;
5377
5378         /* Disable next automatic folder selection */
5379         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5380                                                          FALSE); /* don't create */
5381
5382         /* Show notification dialog only if the main window exists */
5383         if (main_window) {
5384                 GtkWidget *folder_view = NULL;
5385
5386                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5387                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5388                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5389
5390                 if (user_data && TNY_IS_FOLDER (user_data)) {
5391                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5392                                                           TNY_FOLDER (user_data), FALSE);
5393                 }
5394         }
5395 #endif
5396         win = modest_mail_operation_get_source (mail_op);
5397         error = modest_mail_operation_get_error (mail_op);
5398
5399         if (TNY_IS_FOLDER (user_data))
5400                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5401         else if (TNY_IS_ACCOUNT (user_data))
5402                 account = g_object_ref (user_data);
5403
5404         /* If it's not a disk full error then show a generic error */
5405         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5406                                                              (GtkWidget *) win, (GError *) error,
5407                                                              account, NULL))
5408                 modest_platform_run_information_dialog ((GtkWindow *) win,
5409                                                         _("mail_in_ui_folder_move_target_error"),
5410                                                         FALSE);
5411         if (account)
5412                 g_object_unref (account);
5413         if (win)
5414                 g_object_unref (win);
5415 }
5416
5417 #ifndef MODEST_TOOLKIT_HILDON2
5418 static void
5419 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5420                        TnyHeader *header,
5421                        gboolean canceled,
5422                        TnyMsg *msg,
5423                        GError *err,
5424                        gpointer user_data)
5425 {
5426         TnyList *parts;
5427         TnyIterator *iter;
5428         gint pending_purges = 0;
5429         gboolean some_purged = FALSE;
5430         ModestWindow *win = MODEST_WINDOW (user_data);
5431         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5432
5433         /* If there was any error */
5434         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5435                 modest_window_mgr_unregister_header (mgr, header);
5436                 return;
5437         }
5438
5439         /* Once the message has been retrieved for purging, we check if
5440          * it's all ok for purging */
5441
5442         parts = tny_simple_list_new ();
5443         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5444         iter = tny_list_create_iterator (parts);
5445
5446         while (!tny_iterator_is_done (iter)) {
5447                 TnyMimePart *part;
5448                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5449                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5450                         if (tny_mime_part_is_purged (part))
5451                                 some_purged = TRUE;
5452                         else
5453                                 pending_purges++;
5454                 }
5455
5456                 if (part)
5457                         g_object_unref (part);
5458
5459                 tny_iterator_next (iter);
5460         }
5461         g_object_unref (iter);
5462
5463
5464         if (pending_purges>0) {
5465                 gint response;
5466                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5467
5468                 if (response == GTK_RESPONSE_OK) {
5469                         GtkWidget *info;
5470                         info =
5471                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5472                         iter = tny_list_create_iterator (parts);
5473                         while (!tny_iterator_is_done (iter)) {
5474                                 TnyMimePart *part;
5475
5476                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5477                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5478                                         tny_mime_part_set_purged (part);
5479
5480                                 if (part)
5481                                         g_object_unref (part);
5482
5483                                 tny_iterator_next (iter);
5484                         }
5485                         g_object_unref (iter);
5486
5487                         tny_msg_rewrite_cache (msg);
5488
5489                         gtk_widget_destroy (info);
5490                 }
5491         }
5492
5493         modest_window_mgr_unregister_header (mgr, header);
5494
5495         g_object_unref (parts);
5496 }
5497
5498 static void
5499 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5500                                                      ModestMainWindow *win)
5501 {
5502         GtkWidget *header_view;
5503         TnyList *header_list;
5504         TnyHeader *header;
5505         TnyHeaderFlags flags;
5506         ModestWindow *msg_view_window =  NULL;
5507         gboolean found;
5508
5509         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5510
5511         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5512                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5513
5514         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5515         if (!header_list) {
5516                 g_warning ("%s: no header selected", __FUNCTION__);
5517                 return;
5518         }
5519
5520         if (tny_list_get_length (header_list) == 1) {
5521                 TnyIterator *iter = tny_list_create_iterator (header_list);
5522                 header = TNY_HEADER (tny_iterator_get_current (iter));
5523                 g_object_unref (iter);
5524         } else
5525                 return;
5526
5527         if (!header || !TNY_IS_HEADER(header)) {
5528                 g_warning ("%s: header is not valid", __FUNCTION__);
5529                 return;
5530         }
5531
5532         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5533                                                           header, &msg_view_window);
5534         flags = tny_header_get_flags (header);
5535         if (!(flags & TNY_HEADER_FLAG_CACHED))
5536                 return;
5537         if (found) {
5538                 if (msg_view_window != NULL)
5539                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5540                 else {
5541                         /* do nothing; uid was registered before, so window is probably on it's way */
5542                         g_debug ("header %p has already been registered", header);
5543                 }
5544         } else {
5545                 ModestMailOperation *mail_op = NULL;
5546                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5547                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5548                                                                          modest_ui_actions_disk_operations_error_handler,
5549                                                                          NULL, NULL);
5550                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5551                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5552
5553                 g_object_unref (mail_op);
5554         }
5555         if (header)
5556                 g_object_unref (header);
5557         if (header_list)
5558                 g_object_unref (header_list);
5559 }
5560 #endif
5561
5562 /*
5563  * Checks if we need a connection to do the transfer and if the user
5564  * wants to connect to complete it
5565  */
5566 static void
5567 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5568                                        TnyFolderStore *src_folder,
5569                                        TnyList *headers,
5570                                        TnyFolder *dst_folder,
5571                                        gboolean delete_originals,
5572                                        gboolean *need_connection,
5573                                        gboolean *do_xfer)
5574 {
5575         TnyAccount *src_account;
5576         gint uncached_msgs = 0;
5577
5578         /* We don't need any further check if
5579          *
5580          * 1- the source folder is local OR
5581          * 2- the device is already online
5582          */
5583         if (!modest_tny_folder_store_is_remote (src_folder) ||
5584             tny_device_is_online (modest_runtime_get_device())) {
5585                 *need_connection = FALSE;
5586                 *do_xfer = TRUE;
5587                 return;
5588         }
5589
5590         /* We must ask for a connection when
5591          *
5592          *   - the message(s) is not already cached   OR
5593          *   - the message(s) is cached but the leave_on_server setting
5594          * is FALSE (because we need to sync the source folder to
5595          * delete the message from the server (for IMAP we could do it
5596          * offline, it'll take place the next time we get a
5597          * connection)
5598          */
5599         uncached_msgs = header_list_count_uncached_msgs (headers);
5600         src_account = get_account_from_folder_store (src_folder);
5601         if (uncached_msgs > 0) {
5602                 guint num_headers;
5603                 const gchar *msg;
5604
5605                 *need_connection = TRUE;
5606                 num_headers = tny_list_get_length (headers);
5607                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5608
5609                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5610                     GTK_RESPONSE_CANCEL) {
5611                         *do_xfer = FALSE;
5612                 } else {
5613                         *do_xfer = TRUE;
5614                 }
5615         } else {
5616                 /* The transfer is possible and the user wants to */
5617                 *do_xfer = TRUE;
5618
5619                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5620                         const gchar *account_name;
5621                         gboolean leave_on_server;
5622
5623                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5624                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5625                                                                                   account_name);
5626
5627                         if (leave_on_server == TRUE) {
5628                                 *need_connection = FALSE;
5629                         } else {
5630                                 *need_connection = TRUE;
5631                         }
5632                 } else {
5633                         *need_connection = FALSE;
5634                 }
5635         }
5636
5637         /* Frees */
5638         g_object_unref (src_account);
5639 }
5640
5641 static void
5642 xfer_messages_error_handler (ModestMailOperation *mail_op,
5643                              gpointer user_data)
5644 {
5645         GObject *win;
5646         const GError *error;
5647         TnyAccount *account;
5648
5649         win = modest_mail_operation_get_source (mail_op);
5650         error = modest_mail_operation_get_error (mail_op);
5651
5652         /* We cannot get the account from the mail op as that is the
5653            source account and for checking memory full conditions we
5654            need the destination one */
5655         account = TNY_ACCOUNT (user_data);
5656
5657         if (error &&
5658             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5659                                                              (GtkWidget *) win, (GError*) error,
5660                                                              account, _KR("cerm_memory_card_full"))) {
5661                 modest_platform_run_information_dialog ((GtkWindow *) win,
5662                                                         _("mail_in_ui_folder_move_target_error"),
5663                                                         FALSE);
5664         }
5665         if (win)
5666                 g_object_unref (win);
5667 }
5668
5669 typedef struct {
5670         TnyFolderStore *dst_folder;
5671         TnyList *headers;
5672 } XferMsgsHelper;
5673
5674 /**
5675  * Utility function that transfer messages from both the main window
5676  * and the msg view window when using the "Move to" dialog
5677  */
5678 static void
5679 xfer_messages_performer  (gboolean canceled,
5680                           GError *err,
5681                           GtkWindow *parent_window,
5682                           TnyAccount *account,
5683                           gpointer user_data)
5684 {
5685         ModestWindow *win = MODEST_WINDOW (parent_window);
5686         TnyAccount *dst_account = NULL;
5687         gboolean dst_forbids_message_add = FALSE;
5688         XferMsgsHelper *helper;
5689         MoveToHelper *movehelper;
5690         ModestMailOperation *mail_op;
5691
5692         helper = (XferMsgsHelper *) user_data;
5693
5694         if (canceled || err) {
5695                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5696                                                                      (GtkWidget *) parent_window, err,
5697                                                                      account, NULL)) {
5698                         /* Show the proper error message */
5699                         modest_ui_actions_on_account_connection_error (parent_window, account);
5700                 }
5701                 goto end;
5702         }
5703
5704         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5705
5706         /* tinymail will return NULL for local folders it seems */
5707         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5708                                                                                   modest_tny_account_get_protocol_type (dst_account),
5709                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5710
5711         if (dst_forbids_message_add) {
5712                 modest_platform_information_banner (GTK_WIDGET (win),
5713                                                     NULL,
5714                                                     ngettext("mail_in_ui_folder_move_target_error",
5715                                                              "mail_in_ui_folder_move_targets_error",
5716                                                              tny_list_get_length (helper->headers)));
5717                 goto end;
5718         }
5719
5720         movehelper = g_new0 (MoveToHelper, 1);
5721
5722 #ifndef MODEST_TOOLKIT_HILDON2
5723         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5724                                                                _CS("ckct_nw_pasting"));
5725         if (movehelper->banner != NULL)  {
5726                 g_object_ref (movehelper->banner);
5727                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5728         }
5729
5730         if (MODEST_IS_MAIN_WINDOW (win)) {
5731                 GtkWidget *header_view =
5732                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5733                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5734                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5735         }
5736 #endif
5737
5738         /* Perform the mail operation */
5739         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5740                                                                  xfer_messages_error_handler,
5741                                                                  g_object_ref (dst_account),
5742                                                                  g_object_unref);
5743         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5744                                          mail_op);
5745
5746         modest_mail_operation_xfer_msgs (mail_op,
5747                                          helper->headers,
5748                                          TNY_FOLDER (helper->dst_folder),
5749                                          TRUE,
5750                                          msgs_move_to_cb,
5751                                          movehelper);
5752
5753         g_object_unref (G_OBJECT (mail_op));
5754  end:
5755         if (dst_account)
5756                 g_object_unref (dst_account);
5757         g_object_unref (helper->dst_folder);
5758         g_object_unref (helper->headers);
5759         g_slice_free (XferMsgsHelper, helper);
5760 }
5761
5762 typedef struct {
5763         TnyFolder *src_folder;
5764         TnyFolderStore *dst_folder;
5765         gboolean delete_original;
5766         GtkWidget *folder_view;
5767 } MoveFolderInfo;
5768
5769 static void
5770 on_move_folder_cb (gboolean canceled,
5771                    GError *err,
5772                    GtkWindow *parent_window,
5773                    TnyAccount *account,
5774                    gpointer user_data)
5775 {
5776         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5777         GtkTreeSelection *sel;
5778         ModestMailOperation *mail_op = NULL;
5779
5780         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5781                 /* Note that the connection process can fail due to
5782                    memory low conditions as it can not successfully
5783                    store the summary */
5784                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5785                                                                      (GtkWidget*) parent_window, err,
5786                                                                      account, NULL))
5787                         g_debug ("Error connecting when trying to move a folder");
5788
5789                 g_object_unref (G_OBJECT (info->src_folder));
5790                 g_object_unref (G_OBJECT (info->dst_folder));
5791                 g_free (info);
5792                 return;
5793         }
5794
5795         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5796 #ifndef MODEST_TOOLKIT_HILDON2
5797         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5798                         _CS("ckct_nw_pasting"));
5799         if (helper->banner != NULL)  {
5800                 g_object_ref (helper->banner);
5801                 gtk_widget_show (GTK_WIDGET(helper->banner));
5802         }
5803 #endif
5804         /* Clean folder on header view before moving it */
5805         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5806         gtk_tree_selection_unselect_all (sel);
5807
5808         /* Let gtk events run. We need that the folder
5809            view frees its reference to the source
5810            folder *before* issuing the mail operation
5811            so we need the signal handler of selection
5812            changed to happen before the mail
5813            operation
5814         while (gtk_events_pending ())
5815                 gtk_main_iteration ();   */
5816
5817         mail_op =
5818                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5819                                                                modest_ui_actions_move_folder_error_handler,
5820                                                                g_object_ref (info->dst_folder), g_object_unref);
5821         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5822                                          mail_op);
5823
5824 #ifndef MODEST_TOOLKIT_HILDON2
5825         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5826                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5827                                                   TNY_FOLDER (info->dst_folder), TRUE);
5828         }
5829 #endif
5830         modest_mail_operation_xfer_folder (mail_op,
5831                         TNY_FOLDER (info->src_folder),
5832                         info->dst_folder,
5833                         info->delete_original,
5834                         folder_move_to_cb,
5835                         helper);
5836         g_object_unref (G_OBJECT (info->src_folder));
5837
5838         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5839         /* } */
5840
5841         /* Unref mail operation */
5842         g_object_unref (G_OBJECT (mail_op));
5843         g_object_unref (G_OBJECT (info->dst_folder));
5844         g_free (user_data);
5845 }
5846
5847 static TnyAccount *
5848 get_account_from_folder_store (TnyFolderStore *folder_store)
5849 {
5850         if (TNY_IS_ACCOUNT (folder_store))
5851                 return g_object_ref (folder_store);
5852         else
5853                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5854 }
5855
5856 #ifndef MODEST_TOOLKIT_HILDON2
5857 /*
5858  * UI handler for the "Move to" action when invoked from the
5859  * ModestMainWindow
5860  */
5861 static void
5862 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5863                                           GtkWidget *folder_view,
5864                                           TnyFolderStore *dst_folder,
5865                                           ModestMainWindow *win)
5866 {
5867         ModestHeaderView *header_view = NULL;
5868         TnyFolderStore *src_folder = NULL;
5869
5870         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5871
5872         /* Get the source folder */
5873         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5874
5875         /* Get header view */
5876         header_view = (ModestHeaderView *)
5877                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5878
5879         /* Get folder or messages to transfer */
5880         if (gtk_widget_is_focus (folder_view)) {
5881                 gboolean do_xfer = TRUE;
5882
5883                 /* Allow only to transfer folders to the local root folder */
5884                 if (TNY_IS_ACCOUNT (dst_folder) &&
5885                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5886                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5887                         do_xfer = FALSE;
5888                 } else if (!TNY_IS_FOLDER (src_folder)) {
5889                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5890                         do_xfer = FALSE;
5891                 }
5892
5893                 if (do_xfer) {
5894                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5895                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5896
5897                         info->src_folder = g_object_ref (src_folder);
5898                         info->dst_folder = g_object_ref (dst_folder);
5899                         info->delete_original = TRUE;
5900                         info->folder_view = folder_view;
5901
5902                         connect_info->callback = on_move_folder_cb;
5903                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5904                         connect_info->data = info;
5905
5906                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5907                                                                    TNY_FOLDER_STORE (src_folder),
5908                                                                    connect_info);
5909                 }
5910         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5911                 TnyList *headers;
5912
5913                 headers = modest_header_view_get_selected_headers(header_view);
5914
5915                 /* Transfer the messages */
5916                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5917                                                             headers, TNY_FOLDER (dst_folder));
5918
5919                 g_object_unref (headers);
5920         }
5921
5922         /* Frees */
5923         g_object_unref (src_folder);
5924 }
5925 #endif
5926
5927 #ifdef MODEST_TOOLKIT_HILDON2
5928 /*
5929  * UI handler for the "Move to" action when invoked from the
5930  * ModestFolderWindow
5931  */
5932 static void
5933 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5934                                             TnyFolderStore *dst_folder,
5935                                             TnyList *selection,
5936                                             GtkWindow *win)
5937 {
5938         TnyFolderStore *src_folder = NULL;
5939         TnyIterator *iterator;
5940
5941         if (tny_list_get_length (selection) != 1)
5942                 return;
5943
5944         iterator = tny_list_create_iterator (selection);
5945         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5946         g_object_unref (iterator);
5947
5948
5949         gboolean do_xfer = TRUE;
5950
5951         /* Allow only to transfer folders to the local root folder */
5952         if (TNY_IS_ACCOUNT (dst_folder) &&
5953             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5954             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5955                 do_xfer = FALSE;
5956                 /* Show an error */
5957                 modest_platform_run_information_dialog (win,
5958                                                         _("mail_in_ui_folder_move_target_error"),
5959                                                         FALSE);
5960         } else if (!TNY_IS_FOLDER (src_folder)) {
5961                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5962                 do_xfer = FALSE;
5963         }
5964
5965         if (do_xfer) {
5966                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5967                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5968
5969                 info->src_folder = g_object_ref (src_folder);
5970                 info->dst_folder = g_object_ref (dst_folder);
5971                 info->delete_original = TRUE;
5972                 info->folder_view = folder_view;
5973
5974                 connect_info->callback = on_move_folder_cb;
5975                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5976                 connect_info->data = info;
5977
5978                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5979                                                            TNY_FOLDER_STORE (src_folder),
5980                                                            connect_info);
5981         }
5982
5983         /* Frees */
5984         g_object_unref (src_folder);
5985 }
5986 #endif
5987
5988
5989 void
5990 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5991                                             TnyFolder *src_folder,
5992                                             TnyList *headers,
5993                                             TnyFolder *dst_folder)
5994 {
5995         gboolean need_connection = TRUE;
5996         gboolean do_xfer = TRUE;
5997         XferMsgsHelper *helper;
5998
5999         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6000         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6001         g_return_if_fail (TNY_IS_LIST (headers));
6002
6003         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6004                                                headers, TNY_FOLDER (dst_folder),
6005                                                TRUE, &need_connection,
6006                                                &do_xfer);
6007
6008         /* If we don't want to transfer just return */
6009         if (!do_xfer)
6010                 return;
6011
6012         /* Create the helper */
6013         helper = g_slice_new (XferMsgsHelper);
6014         helper->dst_folder = g_object_ref (dst_folder);
6015         helper->headers = g_object_ref (headers);
6016
6017         if (need_connection) {
6018                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6019                 connect_info->callback = xfer_messages_performer;
6020                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6021                 connect_info->data = helper;
6022
6023                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6024                                                            TNY_FOLDER_STORE (src_folder),
6025                                                            connect_info);
6026         } else {
6027                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6028                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6029                                          src_account, helper);
6030                 g_object_unref (src_account);
6031         }
6032 }
6033
6034 /*
6035  * UI handler for the "Move to" action when invoked from the
6036  * ModestMsgViewWindow
6037  */
6038 static void
6039 modest_ui_actions_on_window_move_to (GtkAction *action,
6040                                      TnyList *headers,
6041                                      TnyFolderStore *dst_folder,
6042                                      ModestWindow *win)
6043 {
6044         TnyFolder *src_folder = NULL;
6045
6046         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6047
6048         if (headers) {
6049                 TnyHeader *header = NULL;
6050                 TnyIterator *iter;
6051
6052                 iter = tny_list_create_iterator (headers);
6053                 header = (TnyHeader *) tny_iterator_get_current (iter);
6054                 src_folder = tny_header_get_folder (header);
6055
6056                 /* Transfer the messages */
6057                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6058                                                             headers,
6059                                                             TNY_FOLDER (dst_folder));
6060
6061                 /* Frees */
6062                 g_object_unref (header);
6063                 g_object_unref (iter);
6064                 g_object_unref (src_folder);
6065         }
6066 }
6067
6068 void
6069 modest_ui_actions_on_move_to (GtkAction *action,
6070                               ModestWindow *win)
6071 {
6072         modest_ui_actions_on_edit_mode_move_to (win);
6073 }
6074
6075 gboolean
6076 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6077 {
6078         GtkWidget *dialog = NULL;
6079         MoveToInfo *helper = NULL;
6080         TnyList *list_to_move;
6081
6082         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6083
6084 #ifndef MODEST_TOOLKIT_HILDON2
6085         /* Get the main window if exists */
6086         ModestMainWindow *main_window;
6087         if (MODEST_IS_MAIN_WINDOW (win))
6088                 main_window = MODEST_MAIN_WINDOW (win);
6089         else
6090                 main_window =
6091                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6092                                                                                FALSE)); /* don't create */
6093 #endif
6094
6095         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6096
6097         if (!list_to_move)
6098                 return FALSE;
6099
6100         if (tny_list_get_length (list_to_move) < 1) {
6101                 g_object_unref (list_to_move);
6102                 return FALSE;
6103         }
6104
6105         /* Create and run the dialog */
6106         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6107         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6108                                      GTK_WINDOW (dialog),
6109                                      (GtkWindow *) win);
6110
6111         /* Create helper */
6112         helper = g_slice_new0 (MoveToInfo);
6113         helper->list = list_to_move;
6114         helper->win = win;
6115
6116         /* Listen to response signal */
6117         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6118
6119         /* Show the dialog */
6120         gtk_widget_show (dialog);
6121
6122         return FALSE;
6123 }
6124
6125 /*
6126  * Calls #HeadersFunc for each header already selected in the main
6127  * window or the message currently being shown in the msg view window
6128  */
6129 static void
6130 do_headers_action (ModestWindow *win,
6131                    HeadersFunc func,
6132                    gpointer user_data)
6133 {
6134         TnyList *headers_list = NULL;
6135         TnyIterator *iter = NULL;
6136         TnyHeader *header = NULL;
6137         TnyFolder *folder = NULL;
6138
6139         /* Get headers */
6140         headers_list = get_selected_headers (win);
6141         if (!headers_list)
6142                 return;
6143
6144         /* Get the folder */
6145         iter = tny_list_create_iterator (headers_list);
6146         header = TNY_HEADER (tny_iterator_get_current (iter));
6147         if (header) {
6148                 folder = tny_header_get_folder (header);
6149                 g_object_unref (header);
6150         }
6151
6152         /* Call the function for each header */
6153         while (!tny_iterator_is_done (iter)) {
6154                 header = TNY_HEADER (tny_iterator_get_current (iter));
6155                 func (header, win, user_data);
6156                 g_object_unref (header);
6157                 tny_iterator_next (iter);
6158         }
6159
6160         /* Trick: do a poke status in order to speed up the signaling
6161            of observers */
6162         if (folder) {
6163                 tny_folder_poke_status (folder);
6164                 g_object_unref (folder);
6165         }
6166
6167         /* Frees */
6168         g_object_unref (iter);
6169         g_object_unref (headers_list);
6170 }
6171
6172 void
6173 modest_ui_actions_view_attachment (GtkAction *action,
6174                                    ModestWindow *window)
6175 {
6176         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6177                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6178         } else {
6179                 /* not supported window for this action */
6180                 g_return_if_reached ();
6181         }
6182 }
6183
6184 void
6185 modest_ui_actions_save_attachments (GtkAction *action,
6186                                     ModestWindow *window)
6187 {
6188         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6189
6190                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6191                         return;
6192
6193                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6194         } else {
6195                 /* not supported window for this action */
6196                 g_return_if_reached ();
6197         }
6198 }
6199
6200 void
6201 modest_ui_actions_remove_attachments (GtkAction *action,
6202                                       ModestWindow *window)
6203 {
6204 #ifndef MODEST_TOOLKIT_HILDON2
6205         if (MODEST_IS_MAIN_WINDOW (window)) {
6206                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6207         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6208 #else
6209         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6210 #endif
6211                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6212         } else {
6213                 /* not supported window for this action */
6214                 g_return_if_reached ();
6215         }
6216 }
6217
6218 void
6219 modest_ui_actions_on_settings (GtkAction *action,
6220                                ModestWindow *win)
6221 {
6222         GtkWidget *dialog;
6223
6224         dialog = modest_platform_get_global_settings_dialog ();
6225         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6226         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6227         gtk_widget_show_all (dialog);
6228
6229         gtk_dialog_run (GTK_DIALOG (dialog));
6230
6231         gtk_widget_destroy (dialog);
6232 }
6233
6234 void
6235 modest_ui_actions_on_help (GtkAction *action,
6236                            GtkWindow *win)
6237 {
6238         /* Help app is not available at all in fremantle */
6239 #ifndef MODEST_TOOLKIT_HILDON2
6240         const gchar *help_id;
6241
6242         g_return_if_fail (win && GTK_IS_WINDOW(win));
6243
6244         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6245
6246         if (help_id)
6247                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6248 #endif
6249 }
6250
6251 void
6252 modest_ui_actions_on_csm_help (GtkAction *action,
6253                                GtkWindow *win)
6254 {
6255         /* Help app is not available at all in fremantle */
6256 #ifndef MODEST_TOOLKIT_HILDON2
6257
6258         const gchar* help_id = NULL;
6259         GtkWidget *folder_view;
6260         TnyFolderStore *folder_store;
6261
6262         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6263
6264         /* Get selected folder */
6265         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6266                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6267         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6268
6269         /* Switch help_id */
6270         if (folder_store && TNY_IS_FOLDER (folder_store))
6271                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6272
6273         if (folder_store)
6274                 g_object_unref (folder_store);
6275
6276         if (help_id)
6277                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6278         else
6279                 modest_ui_actions_on_help (action, win);
6280 #endif
6281 }
6282
6283 static void
6284 retrieve_contents_cb (ModestMailOperation *mail_op,
6285                       TnyHeader *header,
6286                       gboolean canceled,
6287                       TnyMsg *msg,
6288                       GError *err,
6289                       gpointer user_data)
6290 {
6291         /* We only need this callback to show an error in case of
6292            memory low condition */
6293         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6294                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6295         }
6296 }
6297
6298 static void
6299 retrieve_msg_contents_performer (gboolean canceled,
6300                                  GError *err,
6301                                  GtkWindow *parent_window,
6302                                  TnyAccount *account,
6303                                  gpointer user_data)
6304 {
6305         ModestMailOperation *mail_op;
6306         TnyList *headers = TNY_LIST (user_data);
6307
6308         if (err || canceled) {
6309                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6310                                                                 (GtkWidget *) parent_window, err,
6311                                                                 account, NULL);
6312                 goto out;
6313         }
6314
6315         /* Create mail operation */
6316         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6317                                                                  modest_ui_actions_disk_operations_error_handler,
6318                                                                  NULL, NULL);
6319         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6320         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6321
6322         /* Frees */
6323         g_object_unref (mail_op);
6324  out:
6325         g_object_unref (headers);
6326         g_object_unref (account);
6327 }
6328
6329 void
6330 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6331                                             ModestWindow *window)
6332 {
6333         TnyList *headers = NULL;
6334         TnyAccount *account = NULL;
6335         TnyIterator *iter = NULL;
6336         TnyHeader *header = NULL;
6337         TnyFolder *folder = NULL;
6338
6339         /* Get headers */
6340         headers = get_selected_headers (window);
6341         if (!headers)
6342                 return;
6343
6344         /* Pick the account */
6345         iter = tny_list_create_iterator (headers);
6346         header = TNY_HEADER (tny_iterator_get_current (iter));
6347         folder = tny_header_get_folder (header);
6348         account = tny_folder_get_account (folder);
6349         g_object_unref (folder);
6350         g_object_unref (header);
6351         g_object_unref (iter);
6352
6353         /* Connect and perform the message retrieval */
6354         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6355                                              g_object_ref (account),
6356                                              retrieve_msg_contents_performer,
6357                                              g_object_ref (headers));
6358
6359         /* Frees */
6360         g_object_unref (account);
6361         g_object_unref (headers);
6362 }
6363
6364 void
6365 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6366 {
6367         g_return_if_fail (MODEST_IS_WINDOW (window));
6368
6369         /* Update dimmed */
6370         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6371 }
6372
6373 void
6374 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6375 {
6376         g_return_if_fail (MODEST_IS_WINDOW (window));
6377
6378         /* Update dimmed */
6379         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6380 }
6381
6382 void
6383 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6384                                           ModestWindow *window)
6385 {
6386         g_return_if_fail (MODEST_IS_WINDOW (window));
6387
6388         /* Update dimmed */
6389         modest_ui_actions_check_menu_dimming_rules (window);
6390 }
6391
6392 void
6393 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6394                                           ModestWindow *window)
6395 {
6396         g_return_if_fail (MODEST_IS_WINDOW (window));
6397
6398         /* Update dimmed */
6399         modest_ui_actions_check_menu_dimming_rules (window);
6400 }
6401
6402 void
6403 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6404                                           ModestWindow *window)
6405 {
6406         g_return_if_fail (MODEST_IS_WINDOW (window));
6407
6408         /* Update dimmed */
6409         modest_ui_actions_check_menu_dimming_rules (window);
6410 }
6411
6412 void
6413 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6414                                             ModestWindow *window)
6415 {
6416         g_return_if_fail (MODEST_IS_WINDOW (window));
6417
6418         /* Update dimmed */
6419         modest_ui_actions_check_menu_dimming_rules (window);
6420 }
6421
6422 void
6423 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6424                                           ModestWindow *window)
6425 {
6426         g_return_if_fail (MODEST_IS_WINDOW (window));
6427
6428         /* Update dimmed */
6429         modest_ui_actions_check_menu_dimming_rules (window);
6430 }
6431
6432 void
6433 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6434                                           ModestWindow *window)
6435 {
6436         g_return_if_fail (MODEST_IS_WINDOW (window));
6437
6438         /* Update dimmed */
6439         modest_ui_actions_check_menu_dimming_rules (window);
6440 }
6441
6442 void
6443 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6444                                                  ModestWindow *window)
6445 {
6446         g_return_if_fail (MODEST_IS_WINDOW (window));
6447
6448         /* Update dimmed */
6449         modest_ui_actions_check_menu_dimming_rules (window);
6450 }
6451
6452 void
6453 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6454                                                      ModestWindow *window)
6455 {
6456         g_return_if_fail (MODEST_IS_WINDOW (window));
6457
6458         /* Update dimmed */
6459         modest_ui_actions_check_menu_dimming_rules (window);
6460 }
6461
6462 void
6463 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6464                                                      ModestWindow *window)
6465 {
6466         g_return_if_fail (MODEST_IS_WINDOW (window));
6467
6468         /* Update dimmed */
6469         modest_ui_actions_check_menu_dimming_rules (window);
6470 }
6471
6472 void
6473 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6474 {
6475         g_return_if_fail (MODEST_IS_WINDOW (window));
6476
6477         /* we check for low-mem; in that case, show a warning, and don't allow
6478          * searching
6479          */
6480         if (modest_platform_check_memory_low (window, TRUE))
6481                 return;
6482
6483         modest_platform_show_search_messages (GTK_WINDOW (window));
6484 }
6485
6486 void
6487 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6488 {
6489         g_return_if_fail (MODEST_IS_WINDOW (win));
6490
6491
6492         /* we check for low-mem; in that case, show a warning, and don't allow
6493          * for the addressbook
6494          */
6495         if (modest_platform_check_memory_low (win, TRUE))
6496                 return;
6497
6498
6499         modest_platform_show_addressbook (GTK_WINDOW (win));
6500 }
6501
6502
6503 void
6504 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6505                                           ModestWindow *window)
6506 {
6507         gboolean active;
6508         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6509
6510         if (GTK_IS_TOGGLE_ACTION (action))
6511                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6512         else
6513                 active = TRUE;
6514
6515         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6516                                                        active);
6517 }
6518
6519 #ifndef MODEST_TOOLKIT_HILDON2
6520 static void
6521 on_send_receive_finished (ModestMailOperation  *mail_op,
6522                            gpointer user_data)
6523 {
6524         GtkWidget *header_view, *folder_view;
6525         TnyFolderStore *folder_store;
6526         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6527
6528         /* Set send/receive operation finished */
6529         modest_main_window_notify_send_receive_completed (main_win);
6530
6531         /* Don't refresh the current folder if there were any errors */
6532         if (modest_mail_operation_get_status (mail_op) !=
6533             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6534                 return;
6535
6536         /* Refresh the current folder if we're viewing a window. We do
6537            this because the user won't be able to see the new mails in
6538            the selected folder after a Send&Receive because it only
6539            performs a poke_status, i.e, only the number of read/unread
6540            messages is updated, but the new headers are not
6541            downloaded */
6542         folder_view = modest_main_window_get_child_widget (main_win,
6543                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6544         if (!folder_view)
6545                 return;
6546
6547         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6548
6549         /* Do not need to refresh INBOX again because the
6550            update_account does it always automatically */
6551         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6552             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6553                 ModestMailOperation *refresh_op;
6554
6555                 header_view = modest_main_window_get_child_widget (main_win,
6556                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6557
6558                 /* We do not need to set the contents style
6559                    because it hasn't changed. We also do not
6560                    need to save the widget status. Just force
6561                    a refresh */
6562                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6563                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6564                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6565                                                       folder_refreshed_cb, main_win);
6566                 g_object_unref (refresh_op);
6567         }
6568
6569         if (folder_store)
6570                 g_object_unref (folder_store);
6571 }
6572 #endif
6573
6574 void
6575 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6576                                                 TnyHeader *header,
6577                                                 TnyMsg *msg,
6578                                                 GError *err,
6579                                                 gpointer user_data)
6580 {
6581         const gchar* server_name = NULL;
6582         TnyTransportAccount *transport;
6583         gchar *message = NULL;
6584         ModestProtocol *protocol;
6585
6586         /* Don't show anything if the user cancelled something or the
6587          * send receive request is not interactive. Authentication
6588          * errors are managed by the account store so no need to show
6589          * a dialog here again */
6590         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6591             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6592             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6593                 return;
6594
6595
6596         /* Get the server name. Note that we could be using a
6597            connection specific transport account */
6598         transport = (TnyTransportAccount *)
6599                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6600         if (transport) {
6601                 ModestTnyAccountStore *acc_store;
6602                 const gchar *acc_name;
6603                 TnyTransportAccount *conn_specific;
6604
6605                 acc_store = modest_runtime_get_account_store();
6606                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6607                 conn_specific = (TnyTransportAccount *)
6608                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6609                 if (conn_specific) {
6610                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6611                         g_object_unref (conn_specific);
6612                 } else {
6613                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6614                 }
6615                 g_object_unref (transport);
6616         }
6617
6618         /* Get protocol */
6619         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6620                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6621                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6622         if (!protocol) {
6623                 g_warning ("%s: Account with no proto", __FUNCTION__);
6624                 return;
6625         }
6626
6627         /* Show the appropriate message text for the GError: */
6628         switch (err->code) {
6629         case TNY_SERVICE_ERROR_CONNECT:
6630                 message = modest_protocol_get_translation (protocol,
6631                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6632                                                            server_name);
6633                 break;
6634         case TNY_SERVICE_ERROR_SEND:
6635                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6636                 break;
6637         case TNY_SERVICE_ERROR_UNAVAILABLE:
6638                 message = modest_protocol_get_translation (protocol,
6639                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6640                                                            server_name);
6641                 break;
6642         default:
6643                 g_warning ("%s: unexpected ERROR %d",
6644                            __FUNCTION__, err->code);
6645                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6646                 break;
6647         }
6648
6649         modest_platform_run_information_dialog (NULL, message, FALSE);
6650         g_free (message);
6651 }
6652
6653 void
6654 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6655                                                 gchar *msg_id,
6656                                                 guint status,
6657                                                 gpointer user_data)
6658 {
6659         ModestWindow *top_window = NULL;
6660         ModestWindowMgr *mgr = NULL;
6661         GtkWidget *header_view = NULL;
6662         TnyFolder *selected_folder = NULL;
6663         TnyFolderType folder_type;
6664
6665         mgr = modest_runtime_get_window_mgr ();
6666         top_window = modest_window_mgr_get_current_top (mgr);
6667
6668         if (!top_window)
6669                 return;
6670
6671 #ifndef MODEST_TOOLKIT_HILDON2
6672         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6673                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6674                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6675         }
6676 #else
6677         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6678                 header_view = (GtkWidget *)
6679                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6680         }
6681 #endif
6682
6683         /* Get selected folder */
6684         if (header_view)
6685                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6686         if (!selected_folder)
6687                 return;
6688
6689         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6690 #if GTK_CHECK_VERSION(2, 8, 0)
6691         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6692         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6693                 GtkTreeViewColumn *tree_column;
6694
6695                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6696                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6697                 if (tree_column)
6698                         gtk_tree_view_column_queue_resize (tree_column);
6699                 }
6700 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6701         gtk_widget_queue_draw (header_view);
6702 #endif
6703
6704 #ifndef MODEST_TOOLKIT_HILDON2
6705         /* Rerun dimming rules, because the message could become deletable for example */
6706         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6707                                                  MODEST_DIMMING_RULES_TOOLBAR);
6708         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6709                                                  MODEST_DIMMING_RULES_MENU);
6710 #endif
6711
6712         /* Free */
6713         g_object_unref (selected_folder);
6714 }
6715
6716 void
6717 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6718                                                TnyAccount *account)
6719 {
6720         ModestProtocolType protocol_type;
6721         ModestProtocol *protocol;
6722         gchar *error_note = NULL;
6723
6724         protocol_type = modest_tny_account_get_protocol_type (account);
6725         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6726                                                                   protocol_type);
6727
6728         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6729         if (error_note == NULL) {
6730                 g_warning ("%s: This should not be reached", __FUNCTION__);
6731         } else {
6732                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6733                 g_free (error_note);
6734         }
6735 }
6736
6737 gchar *
6738 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6739 {
6740         gchar *msg = NULL;
6741         gchar *subject;
6742         TnyFolderStore *folder = NULL;
6743         TnyAccount *account = NULL;
6744         ModestProtocolType proto;
6745         ModestProtocol *protocol;
6746         TnyHeader *header = NULL;
6747
6748 #ifndef MODEST_TOOLKIT_HILDON2
6749         if (MODEST_IS_MAIN_WINDOW (win)) {
6750                 GtkWidget *header_view;
6751                 TnyList* headers = NULL;
6752                 TnyIterator *iter;
6753                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6754                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6755                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6756                 if (!headers || tny_list_get_length (headers) == 0) {
6757                         if (headers)
6758                                 g_object_unref (headers);
6759                         return NULL;
6760                 }
6761                 iter = tny_list_create_iterator (headers);
6762                 header = TNY_HEADER (tny_iterator_get_current (iter));
6763                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6764                 g_object_unref (iter);
6765                 g_object_unref (headers);
6766 #else
6767         if (MODEST_IS_HEADER_WINDOW (win)) {
6768                 GtkWidget *header_view;
6769                 TnyList* headers = NULL;
6770                 TnyIterator *iter;
6771                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6772                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6773                 if (!headers || tny_list_get_length (headers) == 0) {
6774                         if (headers)
6775                                 g_object_unref (headers);
6776                         return NULL;
6777                 }
6778                 iter = tny_list_create_iterator (headers);
6779                 header = TNY_HEADER (tny_iterator_get_current (iter));
6780                 if (header) {
6781                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6782                 } else {
6783                         g_warning ("List should contain headers");
6784                 }
6785                 g_object_unref (iter);
6786                 g_object_unref (headers);
6787 #endif
6788         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6789                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6790                 if (header)
6791                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6792         }
6793
6794         if (!header || !folder)
6795                 goto frees;
6796
6797         /* Get the account type */
6798         account = tny_folder_get_account (TNY_FOLDER (folder));
6799         proto = modest_tny_account_get_protocol_type (account);
6800         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6801                                                                   proto);
6802
6803         subject = tny_header_dup_subject (header);
6804         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6805         if (subject)
6806                 g_free (subject);
6807         if (msg == NULL) {
6808                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6809         }
6810
6811  frees:
6812         /* Frees */
6813         if (account)
6814                 g_object_unref (account);
6815         if (folder)
6816                 g_object_unref (folder);
6817         if (header)
6818                 g_object_unref (header);
6819
6820         return msg;
6821 }
6822
6823 gboolean
6824 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6825                                      const gchar *account_name,
6826                                      const gchar *account_title)
6827 {
6828         ModestAccountMgr *account_mgr;
6829         gchar *txt = NULL;
6830         gint response;
6831         ModestProtocol *protocol;
6832         gboolean removed = FALSE;
6833
6834         g_return_val_if_fail (account_name, FALSE);
6835         g_return_val_if_fail (account_title, FALSE);
6836
6837         account_mgr = modest_runtime_get_account_mgr();
6838
6839         /* The warning text depends on the account type: */
6840         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6841                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6842                                                                                                          account_name));
6843         txt = modest_protocol_get_translation (protocol,
6844                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6845                                                account_title);
6846         if (txt == NULL)
6847                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6848
6849         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6850         g_free (txt);
6851         txt = NULL;
6852
6853         if (response == GTK_RESPONSE_OK) {
6854                 /* Remove account. If it succeeds then it also removes
6855                    the account from the ModestAccountView: */
6856                 gboolean is_default = FALSE;
6857                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6858                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6859                         is_default = TRUE;
6860                 g_free (default_account_name);
6861
6862                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6863                 if (removed) {
6864                         /* Close all email notifications, we cannot
6865                            distinguish if the notification belongs to
6866                            this account or not, so for safety reasons
6867                            we remove them all */
6868                         modest_platform_remove_new_mail_notifications (FALSE);
6869                 } else {
6870                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6871                 }
6872         }
6873         return removed;
6874 }
6875
6876 static void
6877 on_fetch_images_performer (gboolean canceled,
6878                            GError *err,
6879                            GtkWindow *parent_window,
6880                            TnyAccount *account,
6881                            gpointer user_data)
6882 {
6883         if (err || canceled) {
6884                 /* Show an unable to retrieve images ??? */
6885                 return;
6886         }
6887
6888         /* Note that the user could have closed the window while connecting */
6889         if (GTK_WIDGET_VISIBLE (parent_window))
6890                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6891         g_object_unref ((GObject *) user_data);
6892 }
6893
6894 void
6895 modest_ui_actions_on_fetch_images (GtkAction *action,
6896                                    ModestWindow *window)
6897 {
6898         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6899
6900         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6901                                              NULL,
6902                                              on_fetch_images_performer, 
6903                                              g_object_ref (window));
6904 }
6905
6906 void
6907 modest_ui_actions_on_reload_message (const gchar *msg_id)
6908 {
6909         ModestWindow *window = NULL;
6910
6911         g_return_if_fail (msg_id && msg_id[0] != '\0');
6912         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6913                                                             msg_id,
6914                                                             &window))
6915                 return;
6916
6917
6918         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6919                 return;
6920
6921         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6922 }
6923
6924 /** Check whether any connections are active, and cancel them if 
6925  * the user wishes.
6926  * Returns TRUE is there was no problem, 
6927  * or if an operation was cancelled so we can continue.
6928  * Returns FALSE if the user chose to cancel his request instead.
6929  */
6930
6931 gboolean
6932 modest_ui_actions_check_for_active_account (ModestWindow *self,
6933                                             const gchar* account_name)
6934 {
6935         ModestTnySendQueue *send_queue;
6936         ModestTnyAccountStore *acc_store;
6937         ModestMailOperationQueue* queue;
6938         TnyConnectionStatus store_conn_status;
6939         TnyAccount *store_account = NULL, *transport_account = NULL;
6940         gboolean retval = TRUE, sending = FALSE;
6941
6942         acc_store = modest_runtime_get_account_store ();
6943         queue = modest_runtime_get_mail_operation_queue ();
6944
6945         store_account = 
6946                 modest_tny_account_store_get_server_account (acc_store,
6947                                                              account_name,
6948                                                              TNY_ACCOUNT_TYPE_STORE);
6949
6950         /* This could happen if the account was deleted before the
6951            call to this function */
6952         if (!store_account)
6953                 return FALSE;
6954
6955         transport_account = 
6956                 modest_tny_account_store_get_server_account (acc_store,
6957                                                              account_name,
6958                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
6959
6960         /* This could happen if the account was deleted before the
6961            call to this function */
6962         if (!transport_account) {
6963                 g_object_unref (store_account);
6964                 return FALSE;
6965         }
6966
6967         /* If the transport account was not used yet, then the send
6968            queue could not exist (it's created on demand) */
6969         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
6970         if (TNY_IS_SEND_QUEUE (send_queue))
6971                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
6972
6973         store_conn_status = tny_account_get_connection_status (store_account);
6974         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
6975                 gint response;
6976
6977                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
6978                                                                 _("emev_nc_disconnect_account"));
6979                 if (response == GTK_RESPONSE_OK) {
6980                         retval = TRUE;
6981                 } else {
6982                         retval = FALSE;
6983                 }
6984         }
6985
6986         if (retval) {
6987
6988                 /* FIXME: We should only cancel those of this account */
6989                 modest_mail_operation_queue_cancel_all (queue);
6990
6991                 /* Also disconnect the account */
6992                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
6993                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
6994                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
6995                                                       FALSE, NULL, NULL);
6996                 }
6997                 if (sending) {
6998                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
6999                                                       FALSE, NULL, NULL);
7000                 }
7001         }
7002                 
7003         /* Frees */
7004         g_object_unref (store_account);
7005         g_object_unref (transport_account);
7006         
7007         return retval;
7008 }