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