4512dbed6f8efb2013e9d7853743c0044f4bd8e3
[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                 }
2235                 g_object_unref (iterator);
2236
2237                 if (tny_list_get_length (actually_new_list) > 0) {
2238                         modest_platform_on_new_headers_received (actually_new_list,
2239                                                                  show_visual_notifications);
2240                 }
2241                 g_object_unref (actually_new_list);
2242         }
2243
2244 }
2245
2246 gboolean
2247 retrieve_all_messages_cb (GObject *source,
2248                           guint num_msgs,
2249                           guint retrieve_limit)
2250 {
2251         GtkWindow *window;
2252         gchar *msg;
2253         gint response;
2254
2255         window = GTK_WINDOW (source);
2256         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2257                                num_msgs, retrieve_limit);
2258
2259         /* Ask the user if they want to retrieve all the messages */
2260         response =
2261                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2262                                                                       _("mcen_bd_get_all"),
2263                                                                       _("mcen_bd_newest_only"));
2264         /* Free and return */
2265         g_free (msg);
2266         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2267 }
2268
2269 typedef struct {
2270         TnyAccount *account;
2271         ModestWindow *win;
2272         gchar *account_name;
2273         gboolean poke_status;
2274         gboolean interactive;
2275         ModestMailOperation *mail_op;
2276 } SendReceiveInfo;
2277
2278 static void
2279 do_send_receive_performer (gboolean canceled,
2280                            GError *err,
2281                            GtkWindow *parent_window,
2282                            TnyAccount *account,
2283                            gpointer user_data)
2284 {
2285         SendReceiveInfo *info;
2286
2287         info = (SendReceiveInfo *) user_data;
2288
2289         if (err || canceled) {
2290                 /* In memory full conditions we could get this error here */
2291                 check_memory_full_error ((GtkWidget *) parent_window, err);
2292
2293                 if (info->mail_op) {
2294                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2295                                                             info->mail_op);
2296                 }
2297                 goto clean;
2298         }
2299
2300         /* Set send/receive operation in progress */
2301         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2302                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2303         }
2304
2305         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2306                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2307                                   G_CALLBACK (on_send_receive_finished),
2308                                   info->win);
2309
2310         /* Send & receive. */
2311         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2312                                               (info->win) ? retrieve_all_messages_cb : NULL,
2313                                               new_messages_arrived, info->win);
2314
2315  clean:
2316         /* Frees */
2317         if (info->mail_op)
2318                 g_object_unref (G_OBJECT (info->mail_op));
2319         if (info->account_name)
2320                 g_free (info->account_name);
2321         if (info->win)
2322                 g_object_unref (info->win);
2323         if (info->account)
2324                 g_object_unref (info->account);
2325         g_slice_free (SendReceiveInfo, info);
2326 }
2327
2328 /*
2329  * This function performs the send & receive required actions. The
2330  * window is used to create the mail operation. Typically it should
2331  * always be the main window, but we pass it as argument in order to
2332  * be more flexible.
2333  */
2334 void
2335 modest_ui_actions_do_send_receive (const gchar *account_name,
2336                                    gboolean force_connection,
2337                                    gboolean poke_status,
2338                                    gboolean interactive,
2339                                    ModestWindow *win)
2340 {
2341         gchar *acc_name = NULL;
2342         SendReceiveInfo *info;
2343         ModestTnyAccountStore *acc_store;
2344
2345         /* If no account name was provided then get the current account, and if
2346            there is no current account then pick the default one: */
2347         if (!account_name) {
2348                 if (win)
2349                         acc_name = g_strdup (modest_window_get_active_account (win));
2350                 if (!acc_name)
2351                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2352                 if (!acc_name) {
2353                         g_printerr ("modest: cannot get default account\n");
2354                         return;
2355                 }
2356         } else {
2357                 acc_name = g_strdup (account_name);
2358         }
2359
2360         acc_store = modest_runtime_get_account_store ();
2361
2362         /* Create the info for the connect and perform */
2363         info = g_slice_new (SendReceiveInfo);
2364         info->account_name = acc_name;
2365         info->win = (win) ? g_object_ref (win) : NULL;
2366         info->poke_status = poke_status;
2367         info->interactive = interactive;
2368         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
2369                                                                      TNY_ACCOUNT_TYPE_STORE);
2370         /* We need to create the operation here, because otherwise it
2371            could happen that the queue emits the queue-empty signal
2372            while we're trying to connect the account */
2373         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2374                                                                        modest_ui_actions_disk_operations_error_handler,
2375                                                                        NULL, NULL);
2376         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2377
2378         /* Invoke the connect and perform */
2379         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2380                                              force_connection, info->account,
2381                                              do_send_receive_performer, info);
2382 }
2383
2384
2385 static void
2386 modest_ui_actions_do_cancel_send (const gchar *account_name,
2387                                   ModestWindow *win)
2388 {
2389         TnyTransportAccount *transport_account;
2390         TnySendQueue *send_queue = NULL;
2391         GError *error = NULL;
2392
2393         /* Get transport account */
2394         transport_account =
2395                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2396                                       (modest_runtime_get_account_store(),
2397                                        account_name,
2398                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2399         if (!transport_account) {
2400                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2401                 goto frees;
2402         }
2403
2404         /* Get send queue*/
2405         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2406         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2407                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2408                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2409                              "modest: could not find send queue for account\n");
2410         } else {
2411                 /* Cancel the current send */
2412                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2413
2414                 /* Suspend all pending messages */
2415                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2416         }
2417
2418  frees:
2419         if (transport_account != NULL)
2420                 g_object_unref (G_OBJECT (transport_account));
2421 }
2422
2423 static void
2424 modest_ui_actions_cancel_send_all (ModestWindow *win)
2425 {
2426         GSList *account_names, *iter;
2427
2428         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2429                                                           TRUE);
2430
2431         iter = account_names;
2432         while (iter) {
2433                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2434                 iter = g_slist_next (iter);
2435         }
2436
2437         modest_account_mgr_free_account_names (account_names);
2438         account_names = NULL;
2439 }
2440
2441 void
2442 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2443
2444 {
2445         /* Check if accounts exist */
2446         gboolean accounts_exist =
2447                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2448
2449         /* If not, allow the user to create an account before trying to send/receive. */
2450         if (!accounts_exist)
2451                 modest_ui_actions_on_accounts (NULL, win);
2452
2453         /* Cancel all sending operaitons */
2454         modest_ui_actions_cancel_send_all (win);
2455 }
2456
2457 /*
2458  * Refreshes all accounts. This function will be used by automatic
2459  * updates
2460  */
2461 void
2462 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2463                                        gboolean force_connection,
2464                                        gboolean poke_status,
2465                                        gboolean interactive)
2466 {
2467         GSList *account_names, *iter;
2468
2469         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2470                                                           TRUE);
2471
2472         iter = account_names;
2473         while (iter) {
2474                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2475                                                    force_connection,
2476                                                    poke_status, interactive, win);
2477                 iter = g_slist_next (iter);
2478         }
2479
2480         modest_account_mgr_free_account_names (account_names);
2481         account_names = NULL;
2482 }
2483
2484 /*
2485  * Handler of the click on Send&Receive button in the main toolbar
2486  */
2487 void
2488 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2489 {
2490         /* Check if accounts exist */
2491         gboolean accounts_exist;
2492
2493         accounts_exist =
2494                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2495
2496         /* If not, allow the user to create an account before trying to send/receive. */
2497         if (!accounts_exist)
2498                 modest_ui_actions_on_accounts (NULL, win);
2499
2500         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2501         if (MODEST_IS_MAIN_WINDOW (win)) {
2502                 GtkWidget *folder_view;
2503                 TnyFolderStore *folder_store;
2504
2505                 folder_view =
2506                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2507                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2508                 if (!folder_view)
2509                         return;
2510
2511                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2512
2513                 if (folder_store)
2514                         g_object_unref (folder_store);
2515                 /* Refresh the active account. Force the connection if needed
2516                    and poke the status of all folders */
2517                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2518 #ifdef MODEST_TOOLKIT_HILDON2
2519         } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2520                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2521 #endif
2522         } else {
2523                 const gchar *active_account;
2524                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2525
2526                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2527         }
2528
2529 }
2530
2531
2532 void
2533 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2534 {
2535         ModestConf *conf;
2536         GtkWidget *header_view;
2537
2538         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2539
2540         header_view = modest_main_window_get_child_widget (main_window,
2541                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2542         if (!header_view)
2543                 return;
2544
2545         conf = modest_runtime_get_conf ();
2546
2547         /* what is saved/restored is depending on the style; thus; we save with
2548          * old style, then update the style, and restore for this new style
2549          */
2550         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2551
2552         if (modest_header_view_get_style
2553             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2554                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2555                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2556         else
2557                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2558                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2559
2560         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2561                                       MODEST_CONF_HEADER_VIEW_KEY);
2562 }
2563
2564
2565 void
2566 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2567                                       TnyHeader *header,
2568                                       ModestMainWindow *main_window)
2569 {
2570         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2571         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2572
2573         /* in the case the folder is empty, show the empty folder message and focus
2574          * folder view */
2575         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2576                 if (modest_header_view_is_empty (header_view)) {
2577                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2578                         GtkWidget *folder_view =
2579                                 modest_main_window_get_child_widget (main_window,
2580                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2581                         if (folder != NULL) {
2582                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2583                                 g_object_unref (folder);
2584                         }
2585                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2586                         return;
2587                 }
2588         }
2589         /* If no header has been selected then exit */
2590         if (!header)
2591                 return;
2592
2593         /* Update focus */
2594         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2595             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2596
2597         /* Update toolbar dimming state */
2598         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2599         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2600 }
2601
2602 void
2603 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2604                                        TnyHeader *header,
2605                                        GtkTreePath *path,
2606                                        ModestWindow *window)
2607 {
2608         GtkWidget *open_widget;
2609         GtkTreeRowReference *rowref;
2610
2611         g_return_if_fail (MODEST_IS_WINDOW(window));
2612         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2613         g_return_if_fail (TNY_IS_HEADER (header));
2614
2615         if (modest_header_view_count_selected_headers (header_view) > 1) {
2616                 /* Don't allow activation if there are more than one message selected */
2617                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2618                 return;
2619         }
2620
2621         /* we check for low-mem; in that case, show a warning, and don't allow
2622          * activating headers
2623          */
2624         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2625                 return;
2626
2627         if (MODEST_IS_MAIN_WINDOW (window)) {
2628                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2629                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2630                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2631                         return;
2632         }
2633
2634         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2635         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2636         gtk_tree_row_reference_free (rowref);
2637 }
2638
2639 static void
2640 set_active_account_from_tny_account (TnyAccount *account,
2641                                      ModestWindow *window)
2642 {
2643         const gchar *server_acc_name = tny_account_get_id (account);
2644
2645         /* We need the TnyAccount provided by the
2646            account store because that is the one that
2647            knows the name of the Modest account */
2648         TnyAccount *modest_server_account =
2649                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2650                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2651                                                              server_acc_name);
2652         if (!modest_server_account) {
2653                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2654                 return;
2655         }
2656
2657         /* Update active account, but only if it's not a pseudo-account */
2658         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2659             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2660                 const gchar *modest_acc_name =
2661                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2662                 if (modest_acc_name)
2663                         modest_window_set_active_account (window, modest_acc_name);
2664         }
2665
2666         g_object_unref (modest_server_account);
2667 }
2668
2669
2670 static void
2671 folder_refreshed_cb (ModestMailOperation *mail_op,
2672                      TnyFolder *folder,
2673                      gpointer user_data)
2674 {
2675         ModestMainWindow *win = NULL;
2676         GtkWidget *folder_view, *header_view;
2677         const GError *error;
2678
2679         g_return_if_fail (TNY_IS_FOLDER (folder));
2680
2681         win = MODEST_MAIN_WINDOW (user_data);
2682
2683         /* Check if the operation failed due to memory low conditions */
2684         error = modest_mail_operation_get_error (mail_op);
2685         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2686             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2687                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2688                                                         _KR("memr_ib_operation_disabled"),
2689                                                         TRUE);
2690                 return;
2691         }
2692
2693         folder_view =
2694                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2695         header_view =
2696                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2697
2698         if (folder_view) {
2699                 TnyFolderStore *current_folder;
2700
2701                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2702                 if (current_folder) {
2703                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2704                         g_object_unref (current_folder);
2705                         if (different)
2706                                 return;
2707                 }
2708         }
2709
2710         /* Check if folder is empty and set headers view contents style */
2711         if ((tny_folder_get_all_count (folder) == 0) ||
2712             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2713                 modest_main_window_set_contents_style (win,
2714                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2715 }
2716
2717 void
2718 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2719                                                TnyFolderStore *folder_store,
2720                                                gboolean selected,
2721                                                ModestMainWindow *main_window)
2722 {
2723         GtkWidget *header_view;
2724
2725         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2726
2727         header_view = modest_main_window_get_child_widget(main_window,
2728                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2729         if (!header_view)
2730                 return;
2731
2732
2733         if (TNY_IS_ACCOUNT (folder_store)) {
2734                 if (selected) {
2735                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2736
2737                         /* Show account details */
2738                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2739                 }
2740         } else {
2741                 if (TNY_IS_FOLDER (folder_store) && selected) {
2742                         TnyAccount *account;
2743
2744                         /* Update the active account */
2745                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2746                         if (account) {
2747                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2748                                 g_object_unref (account);
2749                                 account = NULL;
2750                         }
2751
2752                         /* Set the header style by default, it could
2753                            be changed later by the refresh callback to
2754                            empty */
2755                         modest_main_window_set_contents_style (main_window,
2756                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2757
2758                         /* Set folder on header view. This function
2759                            will call tny_folder_refresh_async so we
2760                            pass a callback that will be called when
2761                            finished. We use that callback to set the
2762                            empty view if there are no messages */
2763                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2764                                                        TNY_FOLDER (folder_store),
2765                                                        TRUE,
2766                                                        MODEST_WINDOW (main_window),
2767                                                        folder_refreshed_cb,
2768                                                        main_window);
2769
2770                         /* Restore configuration. We need to do this
2771                            *after* the set_folder because the widget
2772                            memory asks the header view about its
2773                            folder  */
2774                         modest_widget_memory_restore (modest_runtime_get_conf (),
2775                                                       G_OBJECT(header_view),
2776                                                       MODEST_CONF_HEADER_VIEW_KEY);
2777                 } else {
2778                         /* No need to save the header view
2779                            configuration for Maemo because it only
2780                            saves the sorting stuff and that it's
2781                            already being done by the sort
2782                            dialog. Remove it when the GNOME version
2783                            has the same behaviour */
2784 #ifdef MODEST_TOOLKIT_GTK
2785                         if (modest_main_window_get_contents_style (main_window) ==
2786                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2787                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2788                                                            G_OBJECT (header_view),
2789                                                            MODEST_CONF_HEADER_VIEW_KEY);
2790 #endif
2791                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2792                 }
2793         }
2794
2795         /* Update dimming state */
2796         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2797         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2798 }
2799
2800 void
2801 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2802                                      ModestWindow *win)
2803 {
2804         GtkWidget *dialog;
2805         gchar *txt, *item;
2806         gboolean online;
2807
2808         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2809
2810         online = tny_device_is_online (modest_runtime_get_device());
2811
2812         if (online) {
2813                 /* already online -- the item is simply not there... */
2814                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2815                                                  GTK_DIALOG_MODAL,
2816                                                  GTK_MESSAGE_WARNING,
2817                                                  GTK_BUTTONS_NONE,
2818                                                  _("The %s you selected cannot be found"),
2819                                                  item);
2820                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2821                 gtk_dialog_run (GTK_DIALOG(dialog));
2822         } else {
2823                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2824                                                       GTK_WINDOW (win),
2825                                                       GTK_DIALOG_MODAL,
2826                                                       _("mcen_bd_dialog_cancel"),
2827                                                       GTK_RESPONSE_REJECT,
2828                                                       _("mcen_bd_dialog_ok"),
2829                                                       GTK_RESPONSE_ACCEPT,
2830                                                       NULL);
2831                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2832                                          "Do you want to get online?"), item);
2833                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2834                                     gtk_label_new (txt), FALSE, FALSE, 0);
2835                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2836                 g_free (txt);
2837
2838                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2839                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2840                         /* TODO: Comment about why is this commented out: */
2841                         /* modest_platform_connect_and_wait (); */
2842                 }
2843         }
2844         gtk_widget_destroy (dialog);
2845 }
2846
2847 void
2848 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2849                                      ModestWindow *win)
2850 {
2851         /* g_message ("%s %s", __FUNCTION__, link); */
2852 }
2853
2854
2855 void
2856 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2857                                         ModestWindow *win)
2858 {
2859         modest_platform_activate_uri (link);
2860 }
2861
2862 void
2863 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2864                                           ModestWindow *win)
2865 {
2866         modest_platform_show_uri_popup (link);
2867 }
2868
2869 void
2870 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2871                                              ModestWindow *win)
2872 {
2873         /* we check for low-mem; in that case, show a warning, and don't allow
2874          * viewing attachments
2875          */
2876         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2877                 return;
2878
2879         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2880 }
2881
2882 void
2883 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2884                                           const gchar *address,
2885                                           ModestWindow *win)
2886 {
2887         /* g_message ("%s %s", __FUNCTION__, address); */
2888 }
2889
2890 static void
2891 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2892                       TnyMsg *saved_draft,
2893                       gpointer user_data)
2894 {
2895         ModestMsgEditWindow *edit_window;
2896
2897         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2898 #ifndef MODEST_TOOLKIT_HILDON2
2899         ModestMainWindow *win;
2900
2901         /* FIXME. Make the header view sensitive again. This is a
2902          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2903          * for details */
2904         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2905                                          modest_runtime_get_window_mgr(), FALSE));
2906         if (win != NULL) {
2907                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2908                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2909                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2910         }
2911 #endif
2912
2913         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2914
2915         /* Set draft is there was no error */
2916         if (!modest_mail_operation_get_error (mail_op))
2917                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2918
2919         g_object_unref(edit_window);
2920 }
2921
2922 static gboolean
2923 enough_space_for_message (ModestMsgEditWindow *edit_window,
2924                           MsgData *data)
2925 {
2926         guint64 available_disk, expected_size;
2927         gint parts_count;
2928         guint64 parts_size;
2929
2930         /* Check size */
2931         available_disk = modest_utils_get_available_space (NULL);
2932         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2933         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2934                                                       data->html_body,
2935                                                       parts_count,
2936                                                       parts_size);
2937
2938         /* Double check: memory full condition or message too big */
2939         if (available_disk < MIN_FREE_SPACE ||
2940             expected_size > available_disk) {
2941                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2942                 modest_platform_information_banner (NULL, NULL, msg);
2943                 g_free (msg);
2944
2945                 return FALSE;
2946         }
2947
2948         /*
2949          * djcb: if we're in low-memory state, we only allow for
2950          * saving messages smaller than
2951          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2952          * should still allow for sending anything critical...
2953          */
2954         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2955             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2956                 return FALSE;
2957
2958         /*
2959          * djcb: we also make sure that the attachments are smaller than the max size
2960          * this is for the case where we'd try to forward a message with attachments
2961          * bigger than our max allowed size, or sending an message from drafts which
2962          * somehow got past our checks when attaching.
2963          */
2964         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2965                 modest_platform_run_information_dialog (
2966                         GTK_WINDOW(edit_window),
2967                         _KR("memr_ib_operation_disabled"),
2968                         TRUE);
2969                 return FALSE;
2970         }
2971
2972         return TRUE;
2973 }
2974
2975 gboolean
2976 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2977 {
2978         TnyTransportAccount *transport_account;
2979         ModestMailOperation *mail_operation;
2980         MsgData *data;
2981         gchar *account_name;
2982         ModestAccountMgr *account_mgr;
2983         gboolean had_error = FALSE;
2984         ModestMainWindow *win = NULL;
2985
2986         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2987
2988         data = modest_msg_edit_window_get_msg_data (edit_window);
2989
2990         /* Check size */
2991         if (!enough_space_for_message (edit_window, data)) {
2992                 modest_msg_edit_window_free_msg_data (edit_window, data);
2993                 return FALSE;
2994         }
2995
2996         account_name = g_strdup (data->account_name);
2997         account_mgr = modest_runtime_get_account_mgr();
2998         if (!account_name)
2999                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3000         if (!account_name)
3001                 account_name = modest_account_mgr_get_default_account (account_mgr);
3002         if (!account_name) {
3003                 g_printerr ("modest: no account found\n");
3004                 modest_msg_edit_window_free_msg_data (edit_window, data);
3005                 return FALSE;
3006         }
3007
3008         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3009                 account_name = g_strdup (data->account_name);
3010         }
3011
3012         transport_account =
3013                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3014                                       (modest_runtime_get_account_store (),
3015                                        account_name,
3016                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3017         if (!transport_account) {
3018                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3019                 g_free (account_name);
3020                 modest_msg_edit_window_free_msg_data (edit_window, data);
3021                 return FALSE;
3022         }
3023
3024         /* Create the mail operation */
3025         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3026                                                                         NULL, NULL);
3027         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3028
3029         modest_mail_operation_save_to_drafts (mail_operation,
3030                                               transport_account,
3031                                               data->draft_msg,
3032                                               data->from,
3033                                               data->to, 
3034                                               data->cc, 
3035                                               data->bcc,
3036                                               data->subject,
3037                                               data->plain_body,
3038                                               data->html_body,
3039                                               data->attachments,
3040                                               data->images,
3041                                               data->priority_flags,
3042                                               data->references,
3043                                               data->in_reply_to,
3044                                               on_save_to_drafts_cb,
3045                                               g_object_ref(edit_window));
3046
3047 #ifdef MODEST_TOOLKIT_HILDON2
3048         /* In hildon2 we always show the information banner on saving to drafts.
3049          * It will be a system information banner in this case.
3050          */
3051         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3052         modest_platform_information_banner (NULL, NULL, text);
3053         g_free (text);
3054 #else
3055         /* Use the main window as the parent of the banner, if the
3056            main window does not exist it won't be shown, if the parent
3057            window exists then it's properly shown. We don't use the
3058            editor window because it could be closed (save to drafts
3059            could happen after closing the window */
3060         win = (ModestMainWindow *)
3061                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3062         if (win) {
3063                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3064                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3065                 g_free (text);
3066         }
3067 #endif
3068         modest_msg_edit_window_set_modified (edit_window, FALSE);
3069
3070         /* Frees */
3071         g_free (account_name);
3072         g_object_unref (G_OBJECT (transport_account));
3073         g_object_unref (G_OBJECT (mail_operation));
3074
3075         modest_msg_edit_window_free_msg_data (edit_window, data);
3076
3077         /* ** FIXME **
3078          * If the drafts folder is selected then make the header view
3079          * insensitive while the message is being saved to drafts
3080          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3081          * is not very clean but it avoids letting the drafts folder
3082          * in an inconsistent state: the user could edit the message
3083          * being saved and undesirable things would happen.
3084          * In the average case the user won't notice anything at
3085          * all. In the worst case (the user is editing a really big
3086          * file from Drafts) the header view will be insensitive
3087          * during the saving process (10 or 20 seconds, depending on
3088          * the message). Anyway this is just a quick workaround: once
3089          * we find a better solution it should be removed
3090          * See NB#65125 (commend #18) for details.
3091          */
3092         if (!had_error && win != NULL) {
3093                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3094                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3095                 if (view != NULL) {
3096                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3097                         if (folder) {
3098                                 if (modest_tny_folder_is_local_folder(folder)) {
3099                                         TnyFolderType folder_type;
3100                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3101                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3102                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3103                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3104                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3105                                         }
3106                                 }
3107                         }
3108                         if (folder != NULL) g_object_unref(folder);
3109                 }
3110         }
3111
3112         return !had_error;
3113 }
3114
3115 /* For instance, when clicking the Send toolbar button when editing a message: */
3116 gboolean
3117 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3118 {
3119         TnyTransportAccount *transport_account = NULL;
3120         gboolean had_error = FALSE;
3121         MsgData *data;
3122         ModestAccountMgr *account_mgr;
3123         gchar *account_name;
3124         ModestMailOperation *mail_operation;
3125
3126         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3127
3128         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3129                 return TRUE;
3130
3131         data = modest_msg_edit_window_get_msg_data (edit_window);
3132
3133         /* Check size */
3134         if (!enough_space_for_message (edit_window, data)) {
3135                 modest_msg_edit_window_free_msg_data (edit_window, data);
3136                 return FALSE;
3137         }
3138
3139         account_mgr = modest_runtime_get_account_mgr();
3140         account_name = g_strdup (data->account_name);
3141         if (!account_name)
3142                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3143
3144         if (!account_name)
3145                 account_name = modest_account_mgr_get_default_account (account_mgr);
3146
3147         if (!account_name) {
3148                 modest_msg_edit_window_free_msg_data (edit_window, data);
3149                 /* Run account setup wizard */
3150                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3151                         return TRUE;
3152                 }
3153         }
3154
3155         /* Get the currently-active transport account for this modest account: */
3156         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3157                 transport_account =
3158                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3159                                               (modest_runtime_get_account_store (),
3160                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3161         }
3162
3163         if (!transport_account) {
3164                 modest_msg_edit_window_free_msg_data (edit_window, data);
3165                 /* Run account setup wizard */
3166                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3167                         return TRUE;
3168         }
3169
3170
3171         /* Create the mail operation */
3172         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3173         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3174
3175         modest_mail_operation_send_new_mail (mail_operation,
3176                                              transport_account,
3177                                              data->draft_msg,
3178                                              data->from,
3179                                              data->to,
3180                                              data->cc,
3181                                              data->bcc,
3182                                              data->subject,
3183                                              data->plain_body,
3184                                              data->html_body,
3185                                              data->attachments,
3186                                              data->images,
3187                                              data->references,
3188                                              data->in_reply_to,
3189                                              data->priority_flags);
3190
3191         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3192                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3193
3194         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3195                 const GError *error = modest_mail_operation_get_error (mail_operation);
3196                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3197                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3198                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3199                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3200                         had_error = TRUE;
3201                 }
3202         }
3203
3204         /* Free data: */
3205         g_free (account_name);
3206         g_object_unref (G_OBJECT (transport_account));
3207         g_object_unref (G_OBJECT (mail_operation));
3208
3209         modest_msg_edit_window_free_msg_data (edit_window, data);
3210
3211         if (!had_error) {
3212                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3213
3214                 /* Save settings and close the window: */
3215                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3216         }
3217
3218         return !had_error;
3219 }
3220
3221 void
3222 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3223                                   ModestMsgEditWindow *window)
3224 {
3225         ModestMsgEditFormatState *format_state = NULL;
3226
3227         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3228         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3229
3230         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3231                 return;
3232
3233         format_state = modest_msg_edit_window_get_format_state (window);
3234         g_return_if_fail (format_state != NULL);
3235
3236         format_state->bold = gtk_toggle_action_get_active (action);
3237         modest_msg_edit_window_set_format_state (window, format_state);
3238         g_free (format_state);
3239
3240 }
3241
3242 void
3243 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3244                                      ModestMsgEditWindow *window)
3245 {
3246         ModestMsgEditFormatState *format_state = NULL;
3247
3248         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3249         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3250
3251         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3252                 return;
3253
3254         format_state = modest_msg_edit_window_get_format_state (window);
3255         g_return_if_fail (format_state != NULL);
3256
3257         format_state->italics = gtk_toggle_action_get_active (action);
3258         modest_msg_edit_window_set_format_state (window, format_state);
3259         g_free (format_state);
3260
3261 }
3262
3263 void
3264 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3265                                      ModestMsgEditWindow *window)
3266 {
3267         ModestMsgEditFormatState *format_state = NULL;
3268
3269         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3270         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3271
3272         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3273                 return;
3274
3275         format_state = modest_msg_edit_window_get_format_state (window);
3276         g_return_if_fail (format_state != NULL);
3277
3278         format_state->bullet = gtk_toggle_action_get_active (action);
3279         modest_msg_edit_window_set_format_state (window, format_state);
3280         g_free (format_state);
3281
3282 }
3283
3284 void
3285 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3286                                      GtkRadioAction *selected,
3287                                      ModestMsgEditWindow *window)
3288 {
3289         ModestMsgEditFormatState *format_state = NULL;
3290         GtkJustification value;
3291
3292         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293
3294         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3295                 return;
3296
3297         value = gtk_radio_action_get_current_value (selected);
3298
3299         format_state = modest_msg_edit_window_get_format_state (window);
3300         g_return_if_fail (format_state != NULL);
3301
3302         format_state->justification = value;
3303         modest_msg_edit_window_set_format_state (window, format_state);
3304         g_free (format_state);
3305 }
3306
3307 void
3308 modest_ui_actions_on_select_editor_color (GtkAction *action,
3309                                           ModestMsgEditWindow *window)
3310 {
3311         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3312         g_return_if_fail (GTK_IS_ACTION (action));
3313
3314         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3315                 return;
3316
3317         modest_msg_edit_window_select_color (window);
3318 }
3319
3320 void
3321 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3322                                                      ModestMsgEditWindow *window)
3323 {
3324         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3325         g_return_if_fail (GTK_IS_ACTION (action));
3326
3327         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3328                 return;
3329
3330         modest_msg_edit_window_select_background_color (window);
3331 }
3332
3333 void
3334 modest_ui_actions_on_insert_image (GObject *object,
3335                                    ModestMsgEditWindow *window)
3336 {
3337         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3338
3339
3340         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3341                 return;
3342
3343         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3344                 return;
3345
3346         modest_msg_edit_window_insert_image (window);
3347 }
3348
3349 void
3350 modest_ui_actions_on_attach_file (GtkAction *action,
3351                                   ModestMsgEditWindow *window)
3352 {
3353         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3354         g_return_if_fail (GTK_IS_ACTION (action));
3355
3356         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3357                 return;
3358
3359         modest_msg_edit_window_offer_attach_file (window);
3360 }
3361
3362 void
3363 modest_ui_actions_on_remove_attachments (GtkAction *action,
3364                                          ModestMsgEditWindow *window)
3365 {
3366         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3367
3368         modest_msg_edit_window_remove_attachments (window, NULL);
3369 }
3370
3371 static void
3372 do_create_folder_cb (ModestMailOperation *mail_op,
3373                      TnyFolderStore *parent_folder,
3374                      TnyFolder *new_folder,
3375                      gpointer user_data)
3376 {
3377         gchar *suggested_name = (gchar *) user_data;
3378         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3379         const GError *error;
3380
3381         error = modest_mail_operation_get_error (mail_op);
3382         if (error) {
3383
3384                 /* Show an error. If there was some problem writing to
3385                    disk, show it, otherwise show the generic folder
3386                    create error. We do it here and not in an error
3387                    handler because the call to do_create_folder will
3388                    stop the main loop in a gtk_dialog_run and then,
3389                    the message won't be shown until that dialog is
3390                    closed */
3391                 modest_ui_actions_disk_operations_error_handler (mail_op,
3392                                                                  _("mail_in_ui_folder_create_error"));
3393
3394                 if (!is_memory_full_error ((GError *) error, mail_op)) {
3395                         /* Try again if there is no full memory condition */
3396                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3397                 }
3398         } else {
3399                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3400                  * FIXME: any other? */
3401                 GtkWidget *folder_view;
3402
3403                 if (MODEST_IS_MAIN_WINDOW(source_win))
3404                         folder_view =
3405                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3406                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3407                 else
3408                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3409                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3410
3411                 /* Select the newly created folder. It could happen
3412                    that the widget is no longer there (i.e. the window
3413                    has been destroyed, so we need to check this */
3414                 if (folder_view)
3415                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3416                                                           new_folder, FALSE);
3417                 g_object_unref (new_folder);
3418         }
3419         /* Free. Note that the first time it'll be NULL so noop */
3420         g_free (suggested_name);
3421         g_object_unref (source_win);
3422 }
3423
3424 typedef struct {
3425         gchar *folder_name;
3426         TnyFolderStore *parent;
3427 } CreateFolderConnect;
3428
3429 static void
3430 do_create_folder_performer (gboolean canceled,
3431                          GError *err,
3432                          GtkWindow *parent_window,
3433                          TnyAccount *account,
3434                          gpointer user_data)
3435 {
3436         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3437         ModestMailOperation *mail_op;
3438
3439         if (canceled || err) {
3440                 /* In memory full conditions we could get this error here */
3441                 check_memory_full_error ((GtkWidget *) parent_window, err);
3442
3443                 /* This happens if we have selected the outbox folder
3444                    as the parent */
3445                 if (err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3446                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3447                         /* Show an error and retry */
3448                         modest_platform_information_banner ((GtkWidget *) parent_window,
3449                                                             NULL,
3450                                                             _("mail_in_ui_folder_create_error"));
3451
3452                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3453                 }
3454
3455                 goto frees;
3456         }
3457
3458         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3459         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3460                                          mail_op);
3461         modest_mail_operation_create_folder (mail_op,
3462                                              helper->parent,
3463                                              (const gchar *) helper->folder_name,
3464                                              do_create_folder_cb,
3465                                              g_strdup (helper->folder_name));
3466         g_object_unref (mail_op);
3467
3468  frees:
3469         if (helper->parent)
3470                 g_object_unref (helper->parent);
3471         if (helper->folder_name)
3472                 g_free (helper->folder_name);
3473         g_slice_free (CreateFolderConnect, helper);
3474 }
3475
3476
3477 static void
3478 do_create_folder (GtkWindow *parent_window,
3479                   TnyFolderStore *suggested_parent,
3480                   const gchar *suggested_name)
3481 {
3482         gint result;
3483         gchar *folder_name = NULL;
3484         TnyFolderStore *parent_folder = NULL;
3485
3486         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3487                                                         suggested_parent,
3488                                                         (gchar *) suggested_name,
3489                                                         &folder_name,
3490                                                         &parent_folder);
3491
3492         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3493                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3494                 helper->folder_name = g_strdup (folder_name);
3495                 helper->parent = g_object_ref (parent_folder);
3496
3497                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3498                                                                TRUE,
3499                                                                parent_folder,
3500                                                                do_create_folder_performer,
3501                                                                helper);
3502         }
3503
3504         if (folder_name)
3505                 g_free (folder_name);
3506         if (parent_folder)
3507                 g_object_unref (parent_folder);
3508 }
3509
3510 static void
3511 modest_ui_actions_create_folder(GtkWidget *parent_window,
3512                                 GtkWidget *folder_view,
3513                                 TnyFolderStore *parent_folder)
3514 {
3515         if (!parent_folder) {
3516 #ifdef MODEST_TOOLKIT_HILDON2
3517                 ModestTnyAccountStore *acc_store;
3518
3519                 acc_store = modest_runtime_get_account_store ();
3520
3521                 parent_folder = (TnyFolderStore *)
3522                         modest_tny_account_store_get_local_folders_account (acc_store);
3523 #else
3524                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3525 #endif
3526         }
3527
3528         if (parent_folder) {
3529                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3530                 g_object_unref (parent_folder);
3531         }
3532 }
3533
3534 void
3535 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3536 {
3537
3538         g_return_if_fail (MODEST_IS_WINDOW(window));
3539
3540         if (MODEST_IS_MAIN_WINDOW (window)) {
3541                 GtkWidget *folder_view;
3542
3543                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3544                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3545                 if (!folder_view)
3546                         return;
3547
3548                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3549 #ifdef MODEST_TOOLKIT_HILDON2
3550         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3551                 GtkWidget *folder_view;
3552
3553                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3554                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3555 #endif
3556         } else {
3557                 g_assert_not_reached ();
3558         }
3559 }
3560
3561 static void
3562 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3563                                                gpointer user_data)
3564 {
3565         const GError *error = NULL;
3566         gchar *message = NULL;
3567         gboolean mem_full;
3568
3569         /* Get error message */
3570         error = modest_mail_operation_get_error (mail_op);
3571         if (!error)
3572                 g_return_if_reached ();
3573
3574         mem_full = is_memory_full_error ((GError *) error, mail_op);
3575         if (mem_full) {
3576                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3577         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3578                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3579                 message = _CS("ckdg_ib_folder_already_exists");
3580         } else if (error->domain == TNY_ERROR_DOMAIN &&
3581                    error->code == TNY_SERVICE_ERROR_STATE) {
3582                 /* This means that the folder is already in use (a
3583                    message is opened for example */
3584                 message = _("emev_ni_internal_error");
3585         } else {
3586                 message = _CS("ckdg_ib_unable_to_rename");
3587         }
3588
3589         /* We don't set a parent for the dialog because the dialog
3590            will be destroyed so the banner won't appear */
3591         modest_platform_information_banner (NULL, NULL, message);
3592
3593         if (mem_full)
3594                 g_free (message);
3595 }
3596
3597 typedef struct {
3598         TnyFolderStore *folder;
3599         gchar *new_name;
3600 } RenameFolderInfo;
3601
3602 static void
3603 on_rename_folder_cb (ModestMailOperation *mail_op,
3604                      TnyFolder *new_folder,
3605                      gpointer user_data)
3606 {
3607         ModestFolderView *folder_view;
3608
3609         /* If the window was closed when renaming a folder, or if
3610          * it's not a main window this will happen */
3611         if (!MODEST_IS_FOLDER_VIEW (user_data))
3612                 return;
3613
3614         folder_view = MODEST_FOLDER_VIEW (user_data);
3615         /* Note that if the rename fails new_folder will be NULL */
3616         if (new_folder) {
3617                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3618         } else {
3619                 modest_folder_view_select_first_inbox_or_local (folder_view);
3620         }
3621         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3622 }
3623
3624 static void
3625 on_rename_folder_performer (gboolean canceled,
3626                             GError *err,
3627                             GtkWindow *parent_window,
3628                             TnyAccount *account,
3629                             gpointer user_data)
3630 {
3631         ModestMailOperation *mail_op = NULL;
3632         GtkTreeSelection *sel = NULL;
3633         GtkWidget *folder_view = NULL;
3634         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3635
3636         if (canceled || err) {
3637                 /* In memory full conditions we could get this error here */
3638                 check_memory_full_error ((GtkWidget *) parent_window, err);
3639         } else {
3640
3641                 mail_op =
3642                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3643                                         modest_ui_actions_rename_folder_error_handler,
3644                                         parent_window, NULL);
3645
3646                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3647                                 mail_op);
3648
3649                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3650
3651                         folder_view = modest_main_window_get_child_widget (
3652                                 MODEST_MAIN_WINDOW (parent_window),
3653                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3654                 }
3655 #ifdef MODEST_TOOLKIT_HILDON2
3656                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3657                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3658                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3659                 }
3660 #endif
3661
3662                 /* Clear the folders view */
3663                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3664                 gtk_tree_selection_unselect_all (sel);
3665
3666                 /* Actually rename the folder */
3667                 modest_mail_operation_rename_folder (mail_op,
3668                                                      TNY_FOLDER (data->folder),
3669                                                      (const gchar *) (data->new_name),
3670                                                      on_rename_folder_cb,
3671                                                      folder_view);
3672                 g_object_unref (mail_op);
3673         }
3674
3675         g_object_unref (data->folder);
3676         g_free (data->new_name);
3677         g_free (data);
3678 }
3679
3680 void
3681 modest_ui_actions_on_rename_folder (GtkAction *action,
3682                                      ModestWindow *window)
3683 {
3684         modest_ui_actions_on_edit_mode_rename_folder (window);
3685 }
3686
3687 gboolean
3688 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3689 {
3690         TnyFolderStore *folder;
3691         GtkWidget *folder_view;
3692         gboolean do_rename = TRUE;
3693
3694         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3695
3696         if (MODEST_IS_MAIN_WINDOW (window)) {
3697                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3698                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3699                 if (!folder_view)
3700                         return FALSE;
3701
3702 #ifdef MODEST_TOOLKIT_HILDON2
3703         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3704                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3705 #endif
3706         } else {
3707                 return FALSE;
3708         }
3709
3710         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3711
3712         if (!folder)
3713                 return FALSE;
3714
3715         if (TNY_IS_FOLDER (folder)) {
3716                 gchar *folder_name = NULL;
3717                 gint response;
3718                 const gchar *current_name;
3719                 TnyFolderStore *parent;
3720
3721                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3722                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3723                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3724                                                                      parent, current_name,
3725                                                                      &folder_name);
3726                 g_object_unref (parent);
3727
3728                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3729                         do_rename = FALSE;
3730                 } else {
3731                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3732                         rename_folder_data->folder = g_object_ref (folder);
3733                         rename_folder_data->new_name = folder_name;
3734                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3735                                         folder, on_rename_folder_performer, rename_folder_data);
3736                 }
3737         }
3738         g_object_unref (folder);
3739         return do_rename;
3740 }
3741
3742 static void
3743 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3744                                                gpointer user_data)
3745 {
3746         GObject *win = modest_mail_operation_get_source (mail_op);
3747
3748         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3749                                                 _("mail_in_ui_folder_delete_error"),
3750                                                 FALSE);
3751         g_object_unref (win);
3752 }
3753
3754 typedef struct {
3755         TnyFolderStore *folder;
3756         gboolean move_to_trash;
3757 } DeleteFolderInfo;
3758
3759 static void
3760 on_delete_folder_cb (gboolean canceled,
3761                   GError *err,
3762                   GtkWindow *parent_window,
3763                   TnyAccount *account,
3764                   gpointer user_data)
3765 {
3766         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3767         GtkWidget *folder_view;
3768         ModestMailOperation *mail_op;
3769         GtkTreeSelection *sel;
3770
3771         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3772                 g_object_unref (G_OBJECT (info->folder));
3773                 g_free (info);
3774                 return;
3775         }
3776
3777         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3778                 folder_view = modest_main_window_get_child_widget (
3779                         MODEST_MAIN_WINDOW (parent_window),
3780                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3781 #ifdef MODEST_TOOLKIT_HILDON2
3782         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3783                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3784 #endif
3785         } else {
3786                 g_object_unref (G_OBJECT (info->folder));
3787                 g_free (info);
3788                 return;
3789         }
3790
3791         /* Unselect the folder before deleting it to free the headers */
3792         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3793         gtk_tree_selection_unselect_all (sel);
3794
3795         /* Create the mail operation */
3796         mail_op =
3797                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3798                                 modest_ui_actions_delete_folder_error_handler,
3799                                 NULL, NULL);
3800
3801         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3802                         mail_op);
3803         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3804
3805         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3806
3807         g_object_unref (G_OBJECT (mail_op));
3808         g_object_unref (G_OBJECT (info->folder));
3809         g_free (info);
3810 }
3811
3812 static gboolean
3813 delete_folder (ModestWindow *window, gboolean move_to_trash)
3814 {
3815         TnyFolderStore *folder;
3816         GtkWidget *folder_view;
3817         gint response;
3818         gchar *message;
3819
3820         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3821
3822         if (MODEST_IS_MAIN_WINDOW (window)) {
3823
3824                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3825                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3826 #ifdef MODEST_TOOLKIT_HILDON2
3827         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3828                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3829 #endif
3830         } else {
3831                 return FALSE;
3832         }
3833         if (!folder_view)
3834                 return FALSE;
3835
3836         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3837
3838         if (!folder)
3839                 return FALSE;
3840
3841         /* Show an error if it's an account */
3842         if (!TNY_IS_FOLDER (folder)) {
3843                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3844                                                         _("mail_in_ui_folder_delete_error"),
3845                                                         FALSE);
3846                 g_object_unref (G_OBJECT (folder));
3847                 return FALSE;
3848         }
3849
3850         /* Ask the user */
3851         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3852                                     tny_folder_get_name (TNY_FOLDER (folder)));
3853         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3854                                                             (const gchar *) message);
3855         g_free (message);
3856
3857         if (response == GTK_RESPONSE_OK) {
3858                 DeleteFolderInfo *info;
3859                 info = g_new0(DeleteFolderInfo, 1);
3860                 info->folder = folder;
3861                 info->move_to_trash = move_to_trash;
3862                 g_object_ref (G_OBJECT (info->folder));
3863                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3864                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3865                                                                TRUE,
3866                                                                TNY_FOLDER_STORE (account),
3867                                                                on_delete_folder_cb, info);
3868                 g_object_unref (account);
3869                 return TRUE;
3870         } else {
3871                 return FALSE;
3872         }
3873         g_object_unref (G_OBJECT (folder));
3874 }
3875
3876 void
3877 modest_ui_actions_on_delete_folder (GtkAction *action,
3878                                     ModestWindow *window)
3879 {
3880         modest_ui_actions_on_edit_mode_delete_folder (window);
3881 }
3882
3883 gboolean
3884 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3885 {
3886         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3887
3888         return delete_folder (window, FALSE);
3889 }
3890
3891 void
3892 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3893 {
3894         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3895
3896         delete_folder (MODEST_WINDOW (main_window), TRUE);
3897 }
3898
3899
3900 typedef struct _PasswordDialogFields {
3901         GtkWidget *username;
3902         GtkWidget *password;
3903         GtkWidget *dialog;
3904 } PasswordDialogFields;
3905
3906 static void
3907 password_dialog_check_field (GtkEditable *editable,
3908                              PasswordDialogFields *fields)
3909 {
3910         const gchar *value;
3911         gboolean any_value_empty = FALSE;
3912
3913 #ifdef MODEST_TOOLKIT_HILDON2
3914         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3915 #else
3916         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3917 #endif
3918         if ((value == NULL) || value[0] == '\0') {
3919                 any_value_empty = TRUE;
3920         }
3921 #ifdef MODEST_TOOLKIT_HILDON2
3922         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3923 #else
3924         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3925 #endif
3926         if ((value == NULL) || value[0] == '\0') {
3927                 any_value_empty = TRUE;
3928         }
3929         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3930 }
3931
3932 void
3933 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3934                                          const gchar* server_account_name,
3935                                          gchar **username,
3936                                          gchar **password,
3937                                          gboolean *cancel,
3938                                          gboolean *remember,
3939                                          ModestMainWindow *main_window)
3940 {
3941         g_return_if_fail(server_account_name);
3942         gboolean completed = FALSE;
3943         PasswordDialogFields *fields = NULL;
3944
3945         /* Initalize output parameters: */
3946         if (cancel)
3947                 *cancel = FALSE;
3948
3949         if (remember)
3950                 *remember = TRUE;
3951
3952 #ifndef MODEST_TOOLKIT_GTK
3953         /* Maemo uses a different (awkward) button order,
3954          * It should probably just use gtk_alternative_dialog_button_order ().
3955          */
3956 #ifdef MODEST_TOOLKIT_HILDON2
3957         GtkWidget *dialog =
3958                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3959                                              NULL,
3960                                              GTK_DIALOG_MODAL,
3961                                              _HL("wdgt_bd_done"),
3962                                              GTK_RESPONSE_ACCEPT,
3963                                              NULL);
3964         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3965                                         HILDON_MARGIN_DOUBLE);
3966 #else
3967         GtkWidget *dialog =
3968                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3969                                              NULL,
3970                                              GTK_DIALOG_MODAL,
3971                                              _("mcen_bd_dialog_ok"),
3972                                              GTK_RESPONSE_ACCEPT,
3973                                              _("mcen_bd_dialog_cancel"),
3974                                              GTK_RESPONSE_REJECT,
3975                                              NULL);
3976 #endif /* MODEST_TOOLKIT_HILDON2 */
3977 #else
3978         GtkWidget *dialog =
3979                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3980                                              NULL,
3981                                              GTK_DIALOG_MODAL,
3982                                              GTK_STOCK_CANCEL,
3983                                              GTK_RESPONSE_REJECT,
3984                                              GTK_STOCK_OK,
3985                                              GTK_RESPONSE_ACCEPT,
3986                                              NULL);
3987 #endif /* MODEST_TOOLKIT_GTK */
3988
3989         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3990
3991         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3992                 modest_runtime_get_account_mgr(), server_account_name);
3993         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3994                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3995                 if (cancel)
3996                         *cancel = TRUE;
3997                 gtk_widget_destroy (dialog);
3998                 return;
3999         }
4000
4001         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4002         GtkWidget *label = gtk_label_new (txt);
4003         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4004         g_free (txt);
4005         g_free (server_name);
4006         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4007                             FALSE, FALSE, 0);
4008         server_name = NULL;
4009
4010         /* username: */
4011         gchar *initial_username = modest_account_mgr_get_server_account_username (
4012                 modest_runtime_get_account_mgr(), server_account_name);
4013
4014 #ifdef MODEST_TOOLKIT_HILDON2
4015         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4016         if (initial_username)
4017                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4018 #else
4019         GtkWidget *entry_username = gtk_entry_new ();
4020         if (initial_username)
4021                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4022 #endif
4023         /* Dim this if a connection has ever succeeded with this username,
4024          * as per the UI spec: */
4025         /* const gboolean username_known =  */
4026         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4027         /*              modest_runtime_get_account_mgr(), server_account_name); */
4028         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4029
4030         /* We drop the username sensitive code and disallow changing it here
4031          * as tinymail does not support really changing the username in the callback
4032          */
4033         gtk_widget_set_sensitive (entry_username, FALSE);
4034
4035 #ifndef MODEST_TOOLKIT_GTK
4036         /* Auto-capitalization is the default, so let's turn it off: */
4037         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4038
4039         /* Create a size group to be used by all captions.
4040          * Note that HildonCaption does not create a default size group if we do not specify one.
4041          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4042         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4043
4044 #ifdef MODEST_TOOLKIT_HILDON2
4045         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4046                                                                   _("mail_fi_username"), FALSE,
4047                                                                   entry_username);
4048 #else
4049         GtkWidget *caption = hildon_caption_new (sizegroup,
4050                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4051 #endif
4052         gtk_widget_show (entry_username);
4053         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4054                 FALSE, FALSE, MODEST_MARGIN_HALF);
4055         gtk_widget_show (caption);
4056 #else
4057         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4058                             TRUE, FALSE, 0);
4059 #endif /* !MODEST_TOOLKIT_GTK */
4060
4061         /* password: */
4062 #ifdef MODEST_TOOLKIT_HILDON2
4063         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4064 #else
4065         GtkWidget *entry_password = gtk_entry_new ();
4066 #endif
4067         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4068         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4069
4070 #ifndef MODEST_TOOLKIT_GTK
4071         /* Auto-capitalization is the default, so let's turn it off: */
4072         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4073                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4074
4075 #ifdef MODEST_TOOLKIT_HILDON2
4076         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4077                                                        _("mail_fi_password"), FALSE,
4078                                                        entry_password);
4079 #else
4080         caption = hildon_caption_new (sizegroup,
4081                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4082 #endif
4083         gtk_widget_show (entry_password);
4084         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4085                 FALSE, FALSE, MODEST_MARGIN_HALF);
4086         gtk_widget_show (caption);
4087         g_object_unref (sizegroup);
4088 #else
4089         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4090                             TRUE, FALSE, 0);
4091 #endif /* !MODEST_TOOLKIT_GTK */
4092
4093         if (initial_username != NULL)
4094                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4095
4096 /* This is not in the Maemo UI spec:
4097         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4098         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4099                             TRUE, FALSE, 0);
4100 */
4101
4102         fields = g_slice_new0 (PasswordDialogFields);
4103         fields->username = entry_username;
4104         fields->password = entry_password;
4105         fields->dialog = dialog;
4106
4107         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4108         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4109         password_dialog_check_field (NULL, fields);
4110
4111         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4112
4113         while (!completed) {
4114
4115                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4116                         if (username) {
4117 #ifdef MODEST_TOOLKIT_HILDON2
4118                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4119 #else
4120                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4121 #endif
4122
4123                                 /* Note that an empty field becomes the "" string */
4124                                 if (*username && strlen (*username) > 0) {
4125                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4126                                                                                         server_account_name,
4127                                                                                         *username);
4128                                         completed = TRUE;
4129
4130                                         const gboolean username_was_changed =
4131                                                 (strcmp (*username, initial_username) != 0);
4132                                         if (username_was_changed) {
4133                                                 g_warning ("%s: tinymail does not yet support changing the "
4134                                                            "username in the get_password() callback.\n", __FUNCTION__);
4135                                         }
4136                                 } else {
4137                                         g_free (*username);
4138                                         *username = NULL;
4139                                         /* Show error */
4140                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4141                                                                             _("mcen_ib_username_pw_incorrect"));
4142                                         completed = FALSE;
4143                                 }
4144                         }
4145
4146                         if (password) {
4147 #ifdef MODEST_TOOLKIT_HILDON2
4148                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4149 #else
4150                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4151 #endif
4152
4153                                 /* We do not save the password in the configuration,
4154                                  * because this function is only called for passwords that should
4155                                  * not be remembered:
4156                                  modest_server_account_set_password (
4157                                  modest_runtime_get_account_mgr(), server_account_name,
4158                                  *password);
4159                                  */
4160                         }
4161                         if (cancel)
4162                                 *cancel   = FALSE;
4163                 } else {
4164 #ifndef MODEST_TOOLKIT_HILDON2
4165                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4166                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4167 #endif
4168                         completed = TRUE;
4169                         if (username)
4170                                 *username = NULL;
4171                         if (password)
4172                                 *password = NULL;
4173                         if (cancel)
4174                                 *cancel   = TRUE;
4175                 }
4176         }
4177
4178 /* This is not in the Maemo UI spec:
4179         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4180                 *remember = TRUE;
4181         else
4182                 *remember = FALSE;
4183 */
4184
4185         g_free (initial_username);
4186         gtk_widget_destroy (dialog);
4187         g_slice_free (PasswordDialogFields, fields);
4188
4189         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4190 }
4191
4192 void
4193 modest_ui_actions_on_cut (GtkAction *action,
4194                           ModestWindow *window)
4195 {
4196         GtkWidget *focused_widget;
4197         GtkClipboard *clipboard;
4198
4199         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4200         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4201         if (GTK_IS_EDITABLE (focused_widget)) {
4202                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4203                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4204                 gtk_clipboard_store (clipboard);
4205         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4206                 GtkTextBuffer *buffer;
4207
4208                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4209                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4210                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4211                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4212                         gtk_clipboard_store (clipboard);
4213                 }
4214         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4215                 TnyList *header_list = modest_header_view_get_selected_headers (
4216                                 MODEST_HEADER_VIEW (focused_widget));
4217                 gboolean continue_download = FALSE;
4218                 gint num_of_unc_msgs;
4219
4220                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4221
4222                 if (num_of_unc_msgs) {
4223                         TnyAccount *account = get_account_from_header_list (header_list);
4224                         if (account) {
4225                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4226                                 g_object_unref (account);
4227                         }
4228                 }
4229
4230                 if (num_of_unc_msgs == 0 || continue_download) {
4231 /*                      modest_platform_information_banner (
4232                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4233                         modest_header_view_cut_selection (
4234                                         MODEST_HEADER_VIEW (focused_widget));
4235                 }
4236
4237                 g_object_unref (header_list);
4238         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4239                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4240         }
4241 }
4242
4243 void
4244 modest_ui_actions_on_copy (GtkAction *action,
4245                            ModestWindow *window)
4246 {
4247         GtkClipboard *clipboard;
4248         GtkWidget *focused_widget;
4249         gboolean copied = TRUE;
4250
4251         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4252         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4253
4254         if (GTK_IS_LABEL (focused_widget)) {
4255                 gchar *selection;
4256                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4257                 gtk_clipboard_set_text (clipboard, selection, -1);
4258                 g_free (selection);
4259                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4260                 gtk_clipboard_store (clipboard);
4261         } else if (GTK_IS_EDITABLE (focused_widget)) {
4262                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4263                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4264                 gtk_clipboard_store (clipboard);
4265         } else if (GTK_IS_HTML (focused_widget)) {
4266                 const gchar *sel;
4267                 int len = -1;
4268                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4269                 if ((sel == NULL) || (sel[0] == '\0')) {
4270                         copied = FALSE;
4271                 } else {
4272                         gtk_html_copy (GTK_HTML (focused_widget));
4273                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4274                         gtk_clipboard_store (clipboard);
4275                 }
4276         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4277                 GtkTextBuffer *buffer;
4278                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4279                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4280                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4281                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4282                         gtk_clipboard_store (clipboard);
4283                 }
4284         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4285                 TnyList *header_list = modest_header_view_get_selected_headers (
4286                                 MODEST_HEADER_VIEW (focused_widget));
4287                 gboolean continue_download = FALSE;
4288                 gint num_of_unc_msgs;
4289
4290                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4291
4292                 if (num_of_unc_msgs) {
4293                         TnyAccount *account = get_account_from_header_list (header_list);
4294                         if (account) {
4295                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4296                                 g_object_unref (account);
4297                         }
4298                 }
4299
4300                 if (num_of_unc_msgs == 0 || continue_download) {
4301                         modest_platform_information_banner (
4302                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4303                         modest_header_view_copy_selection (
4304                                         MODEST_HEADER_VIEW (focused_widget));
4305                 } else
4306                         copied = FALSE;
4307
4308                 g_object_unref (header_list);
4309
4310         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4311                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4312         }
4313
4314         /* Show information banner if there was a copy to clipboard */
4315         if(copied)
4316                 modest_platform_information_banner (
4317                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4318 }
4319
4320 void
4321 modest_ui_actions_on_undo (GtkAction *action,
4322                            ModestWindow *window)
4323 {
4324         ModestEmailClipboard *clipboard = NULL;
4325
4326         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4327                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4328         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4329                 /* Clear clipboard source */
4330                 clipboard = modest_runtime_get_email_clipboard ();
4331                 modest_email_clipboard_clear (clipboard);
4332         }
4333         else {
4334                 g_return_if_reached ();
4335         }
4336 }
4337
4338 void
4339 modest_ui_actions_on_redo (GtkAction *action,
4340                            ModestWindow *window)
4341 {
4342         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4343                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4344         }
4345         else {
4346                 g_return_if_reached ();
4347         }
4348 }
4349
4350
4351 static void
4352 destroy_information_note (ModestMailOperation *mail_op,
4353                           gpointer user_data)
4354 {
4355         /* destroy information note */
4356         gtk_widget_destroy (GTK_WIDGET(user_data));
4357 }
4358
4359 static void
4360 destroy_folder_information_note (ModestMailOperation *mail_op,
4361                                  TnyFolder *new_folder,
4362                                  gpointer user_data)
4363 {
4364         /* destroy information note */
4365         gtk_widget_destroy (GTK_WIDGET(user_data));
4366 }
4367
4368
4369 static void
4370 paste_as_attachment_free (gpointer data)
4371 {
4372         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4373
4374         if (helper->banner) {
4375                 gtk_widget_destroy (helper->banner);
4376                 g_object_unref (helper->banner);
4377         }
4378         g_free (helper);
4379 }
4380
4381 static void
4382 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4383                             TnyHeader *header,
4384                             TnyMsg *msg,
4385                             gpointer userdata)
4386 {
4387         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4388         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4389
4390         if (msg == NULL)
4391                 return;
4392
4393         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4394
4395 }
4396
4397 void
4398 modest_ui_actions_on_paste (GtkAction *action,
4399                             ModestWindow *window)
4400 {
4401         GtkWidget *focused_widget = NULL;
4402         GtkWidget *inf_note = NULL;
4403         ModestMailOperation *mail_op = NULL;
4404
4405         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4406         if (GTK_IS_EDITABLE (focused_widget)) {
4407                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4408         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4409                 ModestEmailClipboard *e_clipboard = NULL;
4410                 e_clipboard = modest_runtime_get_email_clipboard ();
4411                 if (modest_email_clipboard_cleared (e_clipboard)) {
4412                         GtkTextBuffer *buffer;
4413                         GtkClipboard *clipboard;
4414
4415                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4416                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4417                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4418                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4419                         ModestMailOperation *mail_op;
4420                         TnyFolder *src_folder = NULL;
4421                         TnyList *data = NULL;
4422                         gboolean delete;
4423                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4424                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4425                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4426                                                                            _CS("ckct_nw_pasting"));
4427                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4428                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4429                         if (helper->banner != NULL) {
4430                                 g_object_ref (G_OBJECT (helper->banner));
4431                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4432                         }
4433
4434                         if (data != NULL) {
4435                                 modest_mail_operation_get_msgs_full (mail_op,
4436                                                                      data,
4437                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4438                                                                      helper,
4439                                                                      paste_as_attachment_free);
4440                         }
4441                         /* Free */
4442                         if (data)
4443                                 g_object_unref (data);
4444                         if (src_folder)
4445                                 g_object_unref (src_folder);
4446
4447                 }
4448         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4449                 ModestEmailClipboard *clipboard = NULL;
4450                 TnyFolder *src_folder = NULL;
4451                 TnyFolderStore *folder_store = NULL;
4452                 TnyList *data = NULL;
4453                 gboolean delete = FALSE;
4454
4455                 /* Check clipboard source */
4456                 clipboard = modest_runtime_get_email_clipboard ();
4457                 if (modest_email_clipboard_cleared (clipboard))
4458                         return;
4459
4460                 /* Get elements to paste */
4461                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4462
4463                 /* Create a new mail operation */
4464                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4465
4466                 /* Get destination folder */
4467                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4468
4469                 /* transfer messages  */
4470                 if (data != NULL) {
4471                         gint response = 0;
4472
4473                         /* Ask for user confirmation */
4474                         response =
4475                                 modest_ui_actions_msgs_move_to_confirmation (window,
4476                                                                              TNY_FOLDER (folder_store),
4477                                                                              delete,
4478                                                                              data);
4479
4480                         if (response == GTK_RESPONSE_OK) {
4481                                 /* Launch notification */
4482                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4483                                                                              _CS("ckct_nw_pasting"));
4484                                 if (inf_note != NULL)  {
4485                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4486                                         gtk_widget_show (GTK_WIDGET(inf_note));
4487                                 }
4488
4489                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4490                                 modest_mail_operation_xfer_msgs (mail_op,
4491                                                                  data,
4492                                                                  TNY_FOLDER (folder_store),
4493                                                                  delete,
4494                                                                  destroy_information_note,
4495                                                                  inf_note);
4496                         } else {
4497                                 g_object_unref (mail_op);
4498                         }
4499
4500                 } else if (src_folder != NULL) {
4501                         /* Launch notification */
4502                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4503                                                                      _CS("ckct_nw_pasting"));
4504                         if (inf_note != NULL)  {
4505                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4506                                 gtk_widget_show (GTK_WIDGET(inf_note));
4507                         }
4508
4509                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4510                         modest_mail_operation_xfer_folder (mail_op,
4511                                                            src_folder,
4512                                                            folder_store,
4513                                                            delete,
4514                                                            destroy_folder_information_note,
4515                                                            inf_note);
4516                 }
4517
4518                 /* Free */
4519                 if (data != NULL)
4520                         g_object_unref (data);
4521                 if (src_folder != NULL)
4522                         g_object_unref (src_folder);
4523                 if (folder_store != NULL)
4524                         g_object_unref (folder_store);
4525         }
4526 }
4527
4528
4529 void
4530 modest_ui_actions_on_select_all (GtkAction *action,
4531                                  ModestWindow *window)
4532 {
4533         GtkWidget *focused_widget;
4534
4535         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4536         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4537                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4538         } else if (GTK_IS_LABEL (focused_widget)) {
4539                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4540         } else if (GTK_IS_EDITABLE (focused_widget)) {
4541                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4542         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4543                 GtkTextBuffer *buffer;
4544                 GtkTextIter start, end;
4545
4546                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4547                 gtk_text_buffer_get_start_iter (buffer, &start);
4548                 gtk_text_buffer_get_end_iter (buffer, &end);
4549                 gtk_text_buffer_select_range (buffer, &start, &end);
4550         } else if (GTK_IS_HTML (focused_widget)) {
4551                 gtk_html_select_all (GTK_HTML (focused_widget));
4552         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4553                 GtkWidget *header_view = focused_widget;
4554                 GtkTreeSelection *selection = NULL;
4555
4556                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4557                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4558                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4559                 }
4560
4561                 /* Disable window dimming management */
4562                 modest_window_disable_dimming (MODEST_WINDOW(window));
4563
4564                 /* Select all messages */
4565                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4566                 gtk_tree_selection_select_all (selection);
4567
4568                 /* Set focuse on header view */
4569                 gtk_widget_grab_focus (header_view);
4570
4571                 /* Enable window dimming management */
4572                 modest_window_enable_dimming (MODEST_WINDOW(window));
4573                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4574                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4575         }
4576
4577 }
4578
4579 void
4580 modest_ui_actions_on_mark_as_read (GtkAction *action,
4581                                    ModestWindow *window)
4582 {
4583         g_return_if_fail (MODEST_IS_WINDOW(window));
4584
4585         /* Mark each header as read */
4586         do_headers_action (window, headers_action_mark_as_read, NULL);
4587 }
4588
4589 void
4590 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4591                                      ModestWindow *window)
4592 {
4593         g_return_if_fail (MODEST_IS_WINDOW(window));
4594
4595         /* Mark each header as read */
4596         do_headers_action (window, headers_action_mark_as_unread, NULL);
4597 }
4598
4599 void
4600 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4601                                   GtkRadioAction *selected,
4602                                   ModestWindow *window)
4603 {
4604         gint value;
4605
4606         value = gtk_radio_action_get_current_value (selected);
4607         if (MODEST_IS_WINDOW (window)) {
4608                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4609         }
4610 }
4611
4612 void
4613 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4614                                                GtkRadioAction *selected,
4615                                                ModestWindow *window)
4616 {
4617         TnyHeaderFlags flags;
4618         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4619
4620         flags = gtk_radio_action_get_current_value (selected);
4621         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4622 }
4623
4624 void
4625 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4626                                                   GtkRadioAction *selected,
4627                                                   ModestWindow *window)
4628 {
4629         gint file_format;
4630
4631         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4632
4633         file_format = gtk_radio_action_get_current_value (selected);
4634         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4635 }
4636
4637
4638 void
4639 modest_ui_actions_on_zoom_plus (GtkAction *action,
4640                                 ModestWindow *window)
4641 {
4642         g_return_if_fail (MODEST_IS_WINDOW (window));
4643
4644         modest_window_zoom_plus (MODEST_WINDOW (window));
4645 }
4646
4647 void
4648 modest_ui_actions_on_zoom_minus (GtkAction *action,
4649                                  ModestWindow *window)
4650 {
4651         g_return_if_fail (MODEST_IS_WINDOW (window));
4652
4653         modest_window_zoom_minus (MODEST_WINDOW (window));
4654 }
4655
4656 void
4657 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4658                                            ModestWindow *window)
4659 {
4660         ModestWindowMgr *mgr;
4661         gboolean fullscreen, active;
4662         g_return_if_fail (MODEST_IS_WINDOW (window));
4663
4664         mgr = modest_runtime_get_window_mgr ();
4665
4666         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4667         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4668
4669         if (active != fullscreen) {
4670                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4671 #ifndef MODEST_TOOLKIT_HILDON2
4672                 gtk_window_present (GTK_WINDOW (window));
4673 #endif
4674         }
4675 }
4676
4677 void
4678 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4679                                         ModestWindow *window)
4680 {
4681         ModestWindowMgr *mgr;
4682         gboolean fullscreen;
4683
4684         g_return_if_fail (MODEST_IS_WINDOW (window));
4685
4686         mgr = modest_runtime_get_window_mgr ();
4687         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4688         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4689
4690 #ifndef MODEST_TOOLKIT_HILDON2
4691         gtk_window_present (GTK_WINDOW (window));
4692 #endif
4693 }
4694
4695 /*
4696  * Used by modest_ui_actions_on_details to call do_headers_action
4697  */
4698 static void
4699 headers_action_show_details (TnyHeader *header,
4700                              ModestWindow *window,
4701                              gpointer user_data)
4702
4703 {
4704         gboolean async_retrieval;
4705         TnyMsg *msg = NULL;
4706
4707         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4708                 async_retrieval = TRUE;
4709                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4710         } else {
4711                 async_retrieval = FALSE;
4712         }
4713         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4714         if (msg)
4715                 g_object_unref (msg);
4716 }
4717
4718 /*
4719  * Show the header details in a ModestDetailsDialog widget
4720  */
4721 void
4722 modest_ui_actions_on_details (GtkAction *action,
4723                               ModestWindow *win)
4724 {
4725         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4726                 TnyMsg *msg;
4727                 TnyHeader *header;
4728
4729                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4730                 if (!msg)
4731                         return;
4732
4733                 header = tny_msg_get_header (msg);
4734                 if (header) {
4735                         headers_action_show_details (header, win, NULL);
4736                         g_object_unref (header);
4737                 }
4738                 g_object_unref (msg);
4739
4740         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4741                 GtkWidget *folder_view, *header_view;
4742
4743                 /* Check which widget has the focus */
4744                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4745                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4746                 if (gtk_widget_is_focus (folder_view)) {
4747                         TnyFolderStore *folder_store
4748                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4749                         if (!folder_store) {
4750                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4751                                 return;
4752                         }
4753                         /* Show only when it's a folder */
4754                         /* This function should not be called for account items,
4755                          * because we dim the menu item for them. */
4756                         if (TNY_IS_FOLDER (folder_store)) {
4757                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4758                                                                            TNY_FOLDER (folder_store));
4759                         }
4760
4761                         g_object_unref (folder_store);
4762
4763                 } else {
4764                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4765                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4766                         /* Show details of each header */
4767                         do_headers_action (win, headers_action_show_details, header_view);
4768                 }
4769 #ifdef MODEST_TOOLKIT_HILDON2
4770         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4771                 TnyFolder *folder;
4772                 GtkWidget *header_view;
4773
4774                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4775                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4776                 if (folder) {
4777                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4778                                                                    folder);
4779                         g_object_unref (folder);
4780                 }
4781 #endif
4782         }
4783 }
4784
4785 void
4786 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4787                                      ModestMsgEditWindow *window)
4788 {
4789         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4790
4791         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4792 }
4793
4794 void
4795 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4796                                       ModestMsgEditWindow *window)
4797 {
4798         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4799
4800         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4801 }
4802
4803 void
4804 modest_ui_actions_toggle_folders_view (GtkAction *action,
4805                                        ModestMainWindow *main_window)
4806 {
4807         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4808
4809         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4810                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4811         else
4812                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4813 }
4814
4815 void
4816 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4817                                      ModestWindow *window)
4818 {
4819         gboolean active, fullscreen = FALSE;
4820         ModestWindowMgr *mgr;
4821
4822         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4823
4824         /* Check if we want to toggle the toolbar view in fullscreen
4825            or normal mode */
4826         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4827                      "ViewShowToolbarFullScreen")) {
4828                 fullscreen = TRUE;
4829         }
4830
4831         /* Toggle toolbar */
4832         mgr = modest_runtime_get_window_mgr ();
4833         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4834 }
4835
4836 void
4837 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4838                                            ModestMsgEditWindow *window)
4839 {
4840         modest_msg_edit_window_select_font (window);
4841 }
4842
4843
4844 void
4845 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4846                                                   const gchar *display_name,
4847                                                   GtkWindow *window)
4848 {
4849         /* don't update the display name if it was already set;
4850          * updating the display name apparently is expensive */
4851         const gchar* old_name = gtk_window_get_title (window);
4852
4853         if (display_name == NULL)
4854                 display_name = " ";
4855
4856         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4857                 return; /* don't do anything */
4858
4859         /* This is usually used to change the title of the main window, which
4860          * is the one that holds the folder view. Note that this change can
4861          * happen even when the widget doesn't have the focus. */
4862         gtk_window_set_title (window, display_name);
4863
4864 }
4865
4866 void
4867 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4868 {
4869         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4870         modest_msg_edit_window_select_contacts (window);
4871 }
4872
4873 void
4874 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4875 {
4876         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4877         modest_msg_edit_window_check_names (window, FALSE);
4878 }
4879
4880 #ifndef MODEST_TOOLKIT_HILDON2
4881 /*
4882  * This function is used to track changes in the selection of the
4883  * folder view that is inside the "move to" dialog to enable/disable
4884  * the OK button because we do not want the user to select a disallowed
4885  * destination for a folder.
4886  * The user also not desired to be able to use NEW button on items where
4887  * folder creation is not possibel.
4888  */
4889 static void
4890 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4891                                             TnyFolderStore *folder_store,
4892                                             gboolean selected,
4893                                             gpointer user_data)
4894 {
4895         GtkWidget *dialog = NULL;
4896         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4897         gboolean moving_folder = FALSE;
4898         gboolean is_local_account = TRUE;
4899         GtkWidget *folder_view = NULL;
4900         ModestTnyFolderRules rules;
4901
4902         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4903
4904         if (!selected)
4905                 return;
4906
4907         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4908         if (!dialog)
4909                 return;
4910
4911         /* check if folder_store is an remote account */
4912         if (TNY_IS_ACCOUNT (folder_store)) {
4913                 TnyAccount *local_account = NULL;
4914                 TnyAccount *mmc_account = NULL;
4915                 ModestTnyAccountStore *account_store = NULL;
4916
4917                 account_store = modest_runtime_get_account_store ();
4918                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4919                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4920
4921                 if ((gpointer) local_account != (gpointer) folder_store &&
4922                     (gpointer) mmc_account != (gpointer) folder_store) {
4923                         ModestProtocolType proto;
4924                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4925                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4926                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4927                         }
4928                         is_local_account = FALSE;
4929                         /* New button should be dimmed on remote
4930                            POP account root */
4931                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4932                                                                                          proto,
4933                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4934                 }
4935                 g_object_unref (local_account);
4936
4937                 /* It could not exist */
4938                 if (mmc_account)
4939                         g_object_unref (mmc_account);
4940         }
4941
4942         /* Check the target folder rules */
4943         if (TNY_IS_FOLDER (folder_store)) {
4944                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4945                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4946                         ok_sensitive = FALSE;
4947                         new_sensitive = FALSE;
4948                         goto end;
4949                 }
4950         }
4951
4952         /* Check if we're moving a folder */
4953         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4954                 /* Get the widgets */
4955                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4956                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4957                 if (gtk_widget_is_focus (folder_view))
4958                         moving_folder = TRUE;
4959         }
4960
4961         if (moving_folder) {
4962                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4963
4964                 /* Get the folder to move */
4965                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4966
4967                 /* Check that we're not moving to the same folder */
4968                 if (TNY_IS_FOLDER (moved_folder)) {
4969                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4970                         if (parent == folder_store)
4971                                 ok_sensitive = FALSE;
4972                         g_object_unref (parent);
4973                 }
4974
4975                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4976                         /* Do not allow to move to an account unless it's the
4977                            local folders account */
4978                         if (!is_local_account)
4979                                 ok_sensitive = FALSE;
4980                 }
4981
4982                 if (ok_sensitive && (moved_folder == folder_store)) {
4983                         /* Do not allow to move to itself */
4984                         ok_sensitive = FALSE;
4985                 }
4986                 g_object_unref (moved_folder);
4987         } else {
4988                 TnyFolder *src_folder = NULL;
4989
4990                 /* Moving a message */
4991                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4992
4993                         TnyHeader *header = NULL;
4994                         header = modest_msg_view_window_get_header
4995                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4996                         if (!TNY_IS_HEADER(header))
4997                                 g_warning ("%s: could not get source header", __FUNCTION__);
4998                         else
4999                                 src_folder = tny_header_get_folder (header);
5000
5001                         if (header)
5002                                 g_object_unref (header);
5003                 } else {
5004                         src_folder =
5005                                 TNY_FOLDER (modest_folder_view_get_selected
5006                                             (MODEST_FOLDER_VIEW (folder_view)));
5007                 }
5008
5009                 if (TNY_IS_FOLDER(src_folder)) {
5010                         /* Do not allow to move the msg to the same folder */
5011                         /* Do not allow to move the msg to an account */
5012                         if ((gpointer) src_folder == (gpointer) folder_store ||
5013                             TNY_IS_ACCOUNT (folder_store))
5014                                 ok_sensitive = FALSE;
5015                         g_object_unref (src_folder);
5016                 } else
5017                         g_warning ("%s: could not get source folder", __FUNCTION__);
5018         }
5019
5020  end:
5021         /* Set sensitivity of the OK and NEW button */
5022         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5023         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5024 }
5025 #endif
5026
5027 static void
5028 on_move_to_dialog_response (GtkDialog *dialog,
5029                             gint       response,
5030                             gpointer   user_data)
5031 {
5032         GtkWidget *parent_win;
5033         MoveToInfo *helper = NULL;
5034         ModestFolderView *folder_view;
5035         gboolean unset_edit_mode = FALSE;
5036
5037         helper = (MoveToInfo *) user_data;
5038
5039         parent_win = (GtkWidget *) helper->win;
5040         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5041                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5042
5043         switch (response) {
5044                 TnyFolderStore *dst_folder;
5045                 TnyFolderStore *selected;
5046
5047         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5048                 selected = modest_folder_view_get_selected (folder_view);
5049                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5050                 g_object_unref (selected);
5051                 return;
5052         case GTK_RESPONSE_NONE:
5053         case GTK_RESPONSE_CANCEL:
5054         case GTK_RESPONSE_DELETE_EVENT:
5055                 break;
5056         case GTK_RESPONSE_OK:
5057                 dst_folder = modest_folder_view_get_selected (folder_view);
5058
5059                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5060                         /* Clean list to move used for filtering */
5061                         modest_folder_view_set_list_to_move (folder_view, NULL);
5062
5063                         modest_ui_actions_on_main_window_move_to (NULL,
5064                                                                   GTK_WIDGET (folder_view),
5065                                                                   dst_folder,
5066                                                                   MODEST_MAIN_WINDOW (parent_win));
5067 #ifdef MODEST_TOOLKIT_HILDON2
5068                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5069                         /* Clean list to move used for filtering */
5070                         modest_folder_view_set_list_to_move (folder_view, NULL);
5071
5072                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5073                                                                     dst_folder,
5074                                                                     helper->list,
5075                                                                     GTK_WINDOW (parent_win));
5076 #endif
5077                 } else {
5078                         /* if the user selected a root folder
5079                            (account) then do not perform any action */
5080                         if (TNY_IS_ACCOUNT (dst_folder)) {
5081                                 g_signal_stop_emission_by_name (dialog, "response");
5082                                 return;
5083                         }
5084
5085                         /* Clean list to move used for filtering */
5086                         modest_folder_view_set_list_to_move (folder_view, NULL);
5087
5088                         /* Moving from headers window in edit mode */
5089                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5090                                                              dst_folder,
5091                                                              MODEST_WINDOW (parent_win));
5092                 }
5093
5094                 if (dst_folder)
5095                         g_object_unref (dst_folder);
5096
5097                 unset_edit_mode = TRUE;
5098                 break;
5099         default:
5100                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5101         }
5102
5103         /* Free the helper and exit */
5104         if (helper->list)
5105                 g_object_unref (helper->list);
5106         if (unset_edit_mode) {
5107 #ifdef MODEST_TOOLKIT_HILDON2
5108                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5109 #endif
5110         }
5111         g_slice_free (MoveToInfo, helper);
5112         gtk_widget_destroy (GTK_WIDGET (dialog));
5113 }
5114
5115 static GtkWidget*
5116 create_move_to_dialog (GtkWindow *win,
5117                        GtkWidget *folder_view,
5118                        TnyList *list_to_move)
5119 {
5120         GtkWidget *dialog, *tree_view = NULL;
5121
5122         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5123
5124 #ifndef MODEST_TOOLKIT_HILDON2
5125         /* Track changes in the selection to
5126          * disable the OK button whenever "Move to" is not possible
5127          * disbale NEW button whenever New is not possible */
5128         g_signal_connect (tree_view,
5129                           "folder_selection_changed",
5130                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5131                           win);
5132 #endif
5133
5134         /* It could happen that we're trying to move a message from a
5135            window (msg window for example) after the main window was
5136            closed, so we can not just get the model of the folder
5137            view */
5138         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5139                 const gchar *visible_id = NULL;
5140
5141                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5142                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5143                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5144                                                MODEST_FOLDER_VIEW(tree_view));
5145
5146                 visible_id =
5147                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5148
5149                 /* Show the same account than the one that is shown in the main window */
5150                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5151                                                                              visible_id);
5152         } else {
5153                 const gchar *active_account_name = NULL;
5154                 ModestAccountMgr *mgr = NULL;
5155                 ModestAccountSettings *settings = NULL;
5156                 ModestServerAccountSettings *store_settings = NULL;
5157
5158                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5159                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5160                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5161                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5162
5163                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5164                 mgr = modest_runtime_get_account_mgr ();
5165                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5166
5167                 if (settings) {
5168                         const gchar *store_account_name;
5169                         store_settings = modest_account_settings_get_store_settings (settings);
5170                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5171
5172                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5173                                                                                      store_account_name);
5174                         g_object_unref (store_settings);
5175                         g_object_unref (settings);
5176                 }
5177         }
5178
5179         /* we keep a pointer to the embedded folder view, so we can
5180          *   retrieve it with get_folder_view_from_move_to_dialog (see
5181          *   above) later (needed for focus handling)
5182          */
5183         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5184
5185         /* Hide special folders */
5186 #ifndef MODEST_TOOLKIT_HILDON2
5187         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5188 #endif
5189         if (list_to_move)
5190                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5191 #ifndef MODEST_TOOLKIT_HILDON2
5192         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5193 #endif
5194
5195         gtk_widget_show (GTK_WIDGET (tree_view));
5196
5197         return dialog;
5198 }
5199
5200 /*
5201  * Shows a confirmation dialog to the user when we're moving messages
5202  * from a remote server to the local storage. Returns the dialog
5203  * response. If it's other kind of movement then it always returns
5204  * GTK_RESPONSE_OK
5205  *
5206  * This one is used by the next functions:
5207  *      modest_ui_actions_on_paste                      - commented out
5208  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5209  */
5210 gint
5211 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5212                                              TnyFolder *dest_folder,
5213                                              gboolean delete,
5214                                              TnyList *headers)
5215 {
5216         gint response = GTK_RESPONSE_OK;
5217         TnyAccount *account = NULL;
5218         TnyFolder *src_folder = NULL;
5219         TnyIterator *iter = NULL;
5220         TnyHeader *header = NULL;
5221
5222         /* return with OK if the destination is a remote folder */
5223         if (modest_tny_folder_is_remote_folder (dest_folder))
5224                 return GTK_RESPONSE_OK;
5225
5226         /* Get source folder */
5227         iter = tny_list_create_iterator (headers);
5228         header = TNY_HEADER (tny_iterator_get_current (iter));
5229         if (header) {
5230                 src_folder = tny_header_get_folder (header);
5231                 g_object_unref (header);
5232         }
5233         g_object_unref (iter);
5234
5235         /* if no src_folder, message may be an attahcment */
5236         if (src_folder == NULL)
5237                 return GTK_RESPONSE_CANCEL;
5238
5239         /* If the source is a local or MMC folder */
5240         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5241                 g_object_unref (src_folder);
5242                 return GTK_RESPONSE_OK;
5243         }
5244
5245         /* Get the account */
5246         account = tny_folder_get_account (src_folder);
5247
5248         /* now if offline we ask the user */
5249         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5250                 response = GTK_RESPONSE_OK;
5251         else
5252                 response = GTK_RESPONSE_CANCEL;
5253
5254         /* Frees */
5255         g_object_unref (src_folder);
5256         g_object_unref (account);
5257
5258         return response;
5259 }
5260
5261 static void
5262 move_to_helper_destroyer (gpointer user_data)
5263 {
5264         MoveToHelper *helper = (MoveToHelper *) user_data;
5265
5266         /* Close the "Pasting" information banner */
5267         if (helper->banner) {
5268                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5269                 g_object_unref (helper->banner);
5270         }
5271         if (gtk_tree_row_reference_valid (helper->reference)) {
5272                 gtk_tree_row_reference_free (helper->reference);
5273                 helper->reference = NULL;
5274         }
5275         g_free (helper);
5276 }
5277
5278 static void
5279 move_to_cb (ModestMailOperation *mail_op,
5280             gpointer user_data)
5281 {
5282         MoveToHelper *helper = (MoveToHelper *) user_data;
5283         GObject *object = modest_mail_operation_get_source (mail_op);
5284
5285         /* Note that the operation could have failed, in that case do
5286            nothing */
5287         if (modest_mail_operation_get_status (mail_op) !=
5288             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5289                 goto frees;
5290
5291         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5292                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5293
5294                 if (!modest_msg_view_window_select_next_message (self) &&
5295                     !modest_msg_view_window_select_previous_message (self)) {
5296                         /* No more messages to view, so close this window */
5297                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5298                 }
5299         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5300                    gtk_tree_row_reference_valid (helper->reference)) {
5301                 GtkWidget *header_view;
5302                 GtkTreePath *path;
5303                 GtkTreeSelection *sel;
5304
5305                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5306                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5307                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5308                 path = gtk_tree_row_reference_get_path (helper->reference);
5309                 /* We need to unselect the previous one
5310                    because we could be copying instead of
5311                    moving */
5312                 gtk_tree_selection_unselect_all (sel);
5313                 gtk_tree_selection_select_path (sel, path);
5314                 gtk_tree_path_free (path);
5315         }
5316         g_object_unref (object);
5317
5318  frees:
5319         /* Destroy the helper */
5320         move_to_helper_destroyer (helper);
5321 }
5322
5323 static void
5324 folder_move_to_cb (ModestMailOperation *mail_op,
5325                    TnyFolder *new_folder,
5326                    gpointer user_data)
5327 {
5328         GtkWidget *folder_view;
5329         GObject *object;
5330
5331         object = modest_mail_operation_get_source (mail_op);
5332         if (MODEST_IS_MAIN_WINDOW (object)) {
5333                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5334                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5335                 g_object_ref (folder_view);
5336                 g_object_unref (object);
5337                 move_to_cb (mail_op, user_data);
5338                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5339                 g_object_unref (folder_view);
5340         } else {
5341                 move_to_cb (mail_op, user_data);
5342         }
5343 }
5344
5345 static void
5346 msgs_move_to_cb (ModestMailOperation *mail_op,
5347                  gpointer user_data)
5348 {
5349         move_to_cb (mail_op, user_data);
5350 }
5351
5352 void
5353 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5354                                              gpointer user_data)
5355 {
5356         GObject *win = NULL;
5357
5358 #ifndef MODEST_TOOLKIT_HILDON2
5359         ModestWindow *main_window = NULL;
5360
5361         /* Disable next automatic folder selection */
5362         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5363                                                          FALSE); /* don't create */
5364         if (main_window) {
5365                 GtkWidget *folder_view = NULL;
5366
5367                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5368                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5369                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5370
5371                 if (user_data && TNY_IS_FOLDER (user_data)) {
5372                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5373                                                           TNY_FOLDER (user_data), FALSE);
5374                 }
5375         }
5376 #endif
5377         /* Show notification dialog only if the main window exists */
5378         win = modest_mail_operation_get_source (mail_op);
5379         modest_platform_run_information_dialog ((GtkWindow *) win,
5380                                                 _("mail_in_ui_folder_move_target_error"),
5381                                                 FALSE);
5382         if (win)
5383                 g_object_unref (win);
5384 }
5385
5386 static void
5387 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5388                        TnyHeader *header,
5389                        gboolean canceled,
5390                        TnyMsg *msg,
5391                        GError *err,
5392                        gpointer user_data)
5393 {
5394         TnyList *parts;
5395         TnyIterator *iter;
5396         gint pending_purges = 0;
5397         gboolean some_purged = FALSE;
5398         ModestWindow *win = MODEST_WINDOW (user_data);
5399         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5400
5401         /* If there was any error */
5402         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5403                 modest_window_mgr_unregister_header (mgr, header);
5404                 return;
5405         }
5406
5407         /* Once the message has been retrieved for purging, we check if
5408          * it's all ok for purging */
5409
5410         parts = tny_simple_list_new ();
5411         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5412         iter = tny_list_create_iterator (parts);
5413
5414         while (!tny_iterator_is_done (iter)) {
5415                 TnyMimePart *part;
5416                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5417                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5418                         if (tny_mime_part_is_purged (part))
5419                                 some_purged = TRUE;
5420                         else
5421                                 pending_purges++;
5422                 }
5423
5424                 if (part)
5425                         g_object_unref (part);
5426
5427                 tny_iterator_next (iter);
5428         }
5429         g_object_unref (iter);
5430
5431
5432         if (pending_purges>0) {
5433                 gint response;
5434                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5435
5436                 if (response == GTK_RESPONSE_OK) {
5437                         GtkWidget *info;
5438                         info =
5439                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5440                         iter = tny_list_create_iterator (parts);
5441                         while (!tny_iterator_is_done (iter)) {
5442                                 TnyMimePart *part;
5443
5444                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5445                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5446                                         tny_mime_part_set_purged (part);
5447
5448                                 if (part)
5449                                         g_object_unref (part);
5450
5451                                 tny_iterator_next (iter);
5452                         }
5453                         g_object_unref (iter);
5454
5455                         tny_msg_rewrite_cache (msg);
5456
5457                         gtk_widget_destroy (info);
5458                 }
5459         }
5460
5461         modest_window_mgr_unregister_header (mgr, header);
5462
5463         g_object_unref (parts);
5464 }
5465
5466 static void
5467 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5468                                                      ModestMainWindow *win)
5469 {
5470         GtkWidget *header_view;
5471         TnyList *header_list;
5472         TnyHeader *header;
5473         TnyHeaderFlags flags;
5474         ModestWindow *msg_view_window =  NULL;
5475         gboolean found;
5476
5477         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5478
5479         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5480                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5481
5482         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5483         if (!header_list) {
5484                 g_warning ("%s: no header selected", __FUNCTION__);
5485                 return;
5486         }
5487
5488         if (tny_list_get_length (header_list) == 1) {
5489                 TnyIterator *iter = tny_list_create_iterator (header_list);
5490                 header = TNY_HEADER (tny_iterator_get_current (iter));
5491                 g_object_unref (iter);
5492         } else
5493                 return;
5494
5495         if (!header || !TNY_IS_HEADER(header)) {
5496                 g_warning ("%s: header is not valid", __FUNCTION__);
5497                 return;
5498         }
5499
5500         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5501                                                           header, &msg_view_window);
5502         flags = tny_header_get_flags (header);
5503         if (!(flags & TNY_HEADER_FLAG_CACHED))
5504                 return;
5505         if (found) {
5506                 if (msg_view_window != NULL)
5507                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5508                 else {
5509                         /* do nothing; uid was registered before, so window is probably on it's way */
5510                         g_warning ("debug: header %p has already been registered", header);
5511                 }
5512         } else {
5513                 ModestMailOperation *mail_op = NULL;
5514                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5515                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5516                                                                          modest_ui_actions_disk_operations_error_handler,
5517                                                                          NULL, NULL);
5518                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5519                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5520
5521                 g_object_unref (mail_op);
5522         }
5523         if (header)
5524                 g_object_unref (header);
5525         if (header_list)
5526                 g_object_unref (header_list);
5527 }
5528
5529 /*
5530  * Checks if we need a connection to do the transfer and if the user
5531  * wants to connect to complete it
5532  */
5533 static void
5534 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5535                                        TnyFolderStore *src_folder,
5536                                        TnyList *headers,
5537                                        TnyFolder *dst_folder,
5538                                        gboolean delete_originals,
5539                                        gboolean *need_connection,
5540                                        gboolean *do_xfer)
5541 {
5542         TnyAccount *src_account;
5543         gint uncached_msgs = 0;
5544
5545         /* We don't need any further check if
5546          *
5547          * 1- the source folder is local OR
5548          * 2- the device is already online
5549          */
5550         if (!modest_tny_folder_store_is_remote (src_folder) ||
5551             tny_device_is_online (modest_runtime_get_device())) {
5552                 *need_connection = FALSE;
5553                 *do_xfer = TRUE;
5554                 return;
5555         }
5556
5557         /* We must ask for a connection when
5558          *
5559          *   - the message(s) is not already cached   OR
5560          *   - the message(s) is cached but the leave_on_server setting
5561          * is FALSE (because we need to sync the source folder to
5562          * delete the message from the server (for IMAP we could do it
5563          * offline, it'll take place the next time we get a
5564          * connection)
5565          */
5566         uncached_msgs = header_list_count_uncached_msgs (headers);
5567         src_account = get_account_from_folder_store (src_folder);
5568         if (uncached_msgs > 0) {
5569                 guint num_headers;
5570                 const gchar *msg;
5571
5572                 *need_connection = TRUE;
5573                 num_headers = tny_list_get_length (headers);
5574                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5575
5576                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5577                     GTK_RESPONSE_CANCEL) {
5578                         *do_xfer = FALSE;
5579                 } else {
5580                         *do_xfer = TRUE;
5581                 }
5582         } else {
5583                 /* The transfer is possible and the user wants to */
5584                 *do_xfer = TRUE;
5585
5586                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5587                         const gchar *account_name;
5588                         gboolean leave_on_server;
5589
5590                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5591                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5592                                                                                   account_name);
5593
5594                         if (leave_on_server == TRUE) {
5595                                 *need_connection = FALSE;
5596                         } else {
5597                                 *need_connection = TRUE;
5598                         }
5599                 } else {
5600                         *need_connection = FALSE;
5601                 }
5602         }
5603
5604         /* Frees */
5605         g_object_unref (src_account);
5606 }
5607
5608 static void
5609 xfer_messages_error_handler (ModestMailOperation *mail_op,
5610                              gpointer user_data)
5611 {
5612         GObject *win;
5613         const GError *error;
5614
5615         win = modest_mail_operation_get_source (mail_op);
5616         error = modest_mail_operation_get_error (mail_op);
5617
5618         if (error && is_memory_full_error ((GError *) error, mail_op)) {
5619                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
5620                 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
5621                 g_free (msg);
5622         } else {
5623                 modest_platform_run_information_dialog ((GtkWindow *) win,
5624                                                         _("mail_in_ui_folder_move_target_error"),
5625                                                         FALSE);
5626         }
5627         if (win)
5628                 g_object_unref (win);
5629 }
5630
5631 typedef struct {
5632         TnyFolderStore *dst_folder;
5633         TnyList *headers;
5634 } XferMsgsHelper;
5635
5636 /**
5637  * Utility function that transfer messages from both the main window
5638  * and the msg view window when using the "Move to" dialog
5639  */
5640 static void
5641 xfer_messages_performer  (gboolean canceled,
5642                           GError *err,
5643                           GtkWindow *parent_window,
5644                           TnyAccount *account,
5645                           gpointer user_data)
5646 {
5647         ModestWindow *win = MODEST_WINDOW (parent_window);
5648         TnyAccount *dst_account = NULL;
5649         gboolean dst_forbids_message_add = FALSE;
5650         XferMsgsHelper *helper;
5651         MoveToHelper *movehelper;
5652         ModestMailOperation *mail_op;
5653
5654         helper = (XferMsgsHelper *) user_data;
5655
5656         if (canceled || err) {
5657                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5658                         /* Show the proper error message */
5659                         modest_ui_actions_on_account_connection_error (parent_window, account);
5660                 }
5661                 goto end;
5662         }
5663
5664         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5665
5666         /* tinymail will return NULL for local folders it seems */
5667         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5668                                                                                   modest_tny_account_get_protocol_type (dst_account),
5669                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5670         g_object_unref (dst_account);
5671
5672         if (dst_forbids_message_add) {
5673                 modest_platform_information_banner (GTK_WIDGET (win),
5674                                                     NULL,
5675                                                     ngettext("mail_in_ui_folder_move_target_error",
5676                                                              "mail_in_ui_folder_move_targets_error",
5677                                                              tny_list_get_length (helper->headers)));
5678                 goto end;
5679         }
5680
5681         movehelper = g_new0 (MoveToHelper, 1);
5682
5683 #ifndef MODEST_TOOLKIT_HILDON2
5684         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5685                                                                _CS("ckct_nw_pasting"));
5686         if (movehelper->banner != NULL)  {
5687                 g_object_ref (movehelper->banner);
5688                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5689         }
5690 #endif
5691
5692         if (MODEST_IS_MAIN_WINDOW (win)) {
5693                 GtkWidget *header_view =
5694                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5695                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5696                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5697         }
5698
5699         /* Perform the mail operation */
5700         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5701                                                                  xfer_messages_error_handler,
5702                                                                  movehelper, NULL);
5703         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5704                                          mail_op);
5705
5706         modest_mail_operation_xfer_msgs (mail_op,
5707                                          helper->headers,
5708                                          TNY_FOLDER (helper->dst_folder),
5709                                          TRUE,
5710                                          msgs_move_to_cb,
5711                                          movehelper);
5712
5713         g_object_unref (G_OBJECT (mail_op));
5714  end:
5715         g_object_unref (helper->dst_folder);
5716         g_object_unref (helper->headers);
5717         g_slice_free (XferMsgsHelper, helper);
5718 }
5719
5720 typedef struct {
5721         TnyFolder *src_folder;
5722         TnyFolderStore *dst_folder;
5723         gboolean delete_original;
5724         GtkWidget *folder_view;
5725 } MoveFolderInfo;
5726
5727 static void
5728 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5729                 TnyAccount *account, gpointer user_data)
5730 {
5731         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5732         GtkTreeSelection *sel;
5733         ModestMailOperation *mail_op = NULL;
5734
5735         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5736                 g_object_unref (G_OBJECT (info->src_folder));
5737                 g_object_unref (G_OBJECT (info->dst_folder));
5738                 g_free (info);
5739                 return;
5740         }
5741
5742         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5743 #ifndef MODEST_TOOLKIT_HILDON2
5744         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5745                         _CS("ckct_nw_pasting"));
5746         if (helper->banner != NULL)  {
5747                 g_object_ref (helper->banner);
5748                 gtk_widget_show (GTK_WIDGET(helper->banner));
5749         }
5750 #endif
5751         /* Clean folder on header view before moving it */
5752         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5753         gtk_tree_selection_unselect_all (sel);
5754
5755         /* Let gtk events run. We need that the folder
5756            view frees its reference to the source
5757            folder *before* issuing the mail operation
5758            so we need the signal handler of selection
5759            changed to happen before the mail
5760            operation
5761         while (gtk_events_pending ())
5762                 gtk_main_iteration ();   */
5763
5764         mail_op =
5765                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5766                                 modest_ui_actions_move_folder_error_handler,
5767                                 info->src_folder, NULL);
5768         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5769                         mail_op);
5770
5771         /* Select *after* the changes */
5772         /* TODO: this function hangs UI after transfer */
5773         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5774         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5775
5776         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5777                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5778                                                   TNY_FOLDER (info->dst_folder), TRUE);
5779         }
5780         modest_mail_operation_xfer_folder (mail_op,
5781                         TNY_FOLDER (info->src_folder),
5782                         info->dst_folder,
5783                         info->delete_original,
5784                         folder_move_to_cb,
5785                         helper);
5786         g_object_unref (G_OBJECT (info->src_folder));
5787
5788         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5789         /* } */
5790
5791         /* Unref mail operation */
5792         g_object_unref (G_OBJECT (mail_op));
5793         g_object_unref (G_OBJECT (info->dst_folder));
5794         g_free (user_data);
5795 }
5796
5797 static TnyAccount *
5798 get_account_from_folder_store (TnyFolderStore *folder_store)
5799 {
5800         if (TNY_IS_ACCOUNT (folder_store))
5801                 return g_object_ref (folder_store);
5802         else
5803                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5804 }
5805
5806 /*
5807  * UI handler for the "Move to" action when invoked from the
5808  * ModestMainWindow
5809  */
5810 static void
5811 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5812                                           GtkWidget *folder_view,
5813                                           TnyFolderStore *dst_folder,
5814                                           ModestMainWindow *win)
5815 {
5816         ModestHeaderView *header_view = NULL;
5817         TnyFolderStore *src_folder = NULL;
5818
5819         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5820
5821         /* Get the source folder */
5822         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5823
5824         /* Get header view */
5825         header_view = (ModestHeaderView *)
5826                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5827
5828         /* Get folder or messages to transfer */
5829         if (gtk_widget_is_focus (folder_view)) {
5830                 gboolean do_xfer = TRUE;
5831
5832                 /* Allow only to transfer folders to the local root folder */
5833                 if (TNY_IS_ACCOUNT (dst_folder) &&
5834                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5835                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5836                         do_xfer = FALSE;
5837                 } else if (!TNY_IS_FOLDER (src_folder)) {
5838                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5839                         do_xfer = FALSE;
5840                 }
5841
5842                 if (do_xfer) {
5843                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5844                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5845
5846                         info->src_folder = g_object_ref (src_folder);
5847                         info->dst_folder = g_object_ref (dst_folder);
5848                         info->delete_original = TRUE;
5849                         info->folder_view = folder_view;
5850
5851                         connect_info->callback = on_move_folder_cb;
5852                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5853                         connect_info->data = info;
5854
5855                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5856                                                                    TNY_FOLDER_STORE (src_folder),
5857                                                                    connect_info);
5858                 }
5859         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5860                 TnyList *headers;
5861
5862                 headers = modest_header_view_get_selected_headers(header_view);
5863
5864                 /* Transfer the messages */
5865                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5866                                                             headers, TNY_FOLDER (dst_folder));
5867
5868                 g_object_unref (headers);
5869         }
5870
5871         /* Frees */
5872         g_object_unref (src_folder);
5873 }
5874
5875 #ifdef MODEST_TOOLKIT_HILDON2
5876 /*
5877  * UI handler for the "Move to" action when invoked from the
5878  * ModestFolderWindow
5879  */
5880 static void
5881 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5882                                             TnyFolderStore *dst_folder,
5883                                             TnyList *selection,
5884                                             GtkWindow *win)
5885 {
5886         TnyFolderStore *src_folder = NULL;
5887         TnyIterator *iterator;
5888
5889         if (tny_list_get_length (selection) != 1)
5890                 return;
5891
5892         iterator = tny_list_create_iterator (selection);
5893         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5894         g_object_unref (iterator);
5895
5896
5897         gboolean do_xfer = TRUE;
5898
5899         /* Allow only to transfer folders to the local root folder */
5900         if (TNY_IS_ACCOUNT (dst_folder) &&
5901             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5902             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5903                 do_xfer = FALSE;
5904                 /* Show an error */
5905                 modest_platform_run_information_dialog (win,
5906                                                         _("mail_in_ui_folder_move_target_error"),
5907                                                         FALSE);
5908         } else if (!TNY_IS_FOLDER (src_folder)) {
5909                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5910                 do_xfer = FALSE;
5911         }
5912
5913         if (do_xfer) {
5914                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5915                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5916
5917                 info->src_folder = g_object_ref (src_folder);
5918                 info->dst_folder = g_object_ref (dst_folder);
5919                 info->delete_original = TRUE;
5920                 info->folder_view = folder_view;
5921
5922                 connect_info->callback = on_move_folder_cb;
5923                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5924                 connect_info->data = info;
5925
5926                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5927                                                            TNY_FOLDER_STORE (src_folder),
5928                                                            connect_info);
5929         }
5930
5931         /* Frees */
5932         g_object_unref (src_folder);
5933 }
5934 #endif
5935
5936
5937 void
5938 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5939                                             TnyFolder *src_folder,
5940                                             TnyList *headers,
5941                                             TnyFolder *dst_folder)
5942 {
5943         gboolean need_connection = TRUE;
5944         gboolean do_xfer = TRUE;
5945         XferMsgsHelper *helper;
5946
5947         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5948         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5949         g_return_if_fail (TNY_IS_LIST (headers));
5950
5951         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5952                                                headers, TNY_FOLDER (dst_folder),
5953                                                TRUE, &need_connection,
5954                                                &do_xfer);
5955
5956         /* If we don't want to transfer just return */
5957         if (!do_xfer)
5958                 return;
5959
5960         /* Create the helper */
5961         helper = g_slice_new (XferMsgsHelper);
5962         helper->dst_folder = g_object_ref (dst_folder);
5963         helper->headers = g_object_ref (headers);
5964
5965         if (need_connection) {
5966                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5967                 connect_info->callback = xfer_messages_performer;
5968                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5969                 connect_info->data = helper;
5970
5971                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5972                                                            TNY_FOLDER_STORE (src_folder),
5973                                                            connect_info);
5974         } else {
5975                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5976                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5977                                          src_account, helper);
5978                 g_object_unref (src_account);
5979         }
5980 }
5981
5982 /*
5983  * UI handler for the "Move to" action when invoked from the
5984  * ModestMsgViewWindow
5985  */
5986 static void
5987 modest_ui_actions_on_window_move_to (GtkAction *action,
5988                                      TnyList *headers,
5989                                      TnyFolderStore *dst_folder,
5990                                      ModestWindow *win)
5991 {
5992         TnyFolder *src_folder = NULL;
5993
5994         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5995
5996         if (headers) {
5997                 TnyHeader *header = NULL;
5998                 TnyIterator *iter;
5999
6000                 iter = tny_list_create_iterator (headers);
6001                 header = (TnyHeader *) tny_iterator_get_current (iter);
6002                 src_folder = tny_header_get_folder (header);
6003
6004                 /* Transfer the messages */
6005                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6006                                                             headers,
6007                                                             TNY_FOLDER (dst_folder));
6008
6009                 /* Frees */
6010                 g_object_unref (header);
6011                 g_object_unref (iter);
6012                 g_object_unref (src_folder);
6013         }
6014 }
6015
6016 void
6017 modest_ui_actions_on_move_to (GtkAction *action,
6018                               ModestWindow *win)
6019 {
6020         modest_ui_actions_on_edit_mode_move_to (win);
6021 }
6022
6023 gboolean
6024 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6025 {
6026         GtkWidget *dialog = NULL;
6027         MoveToInfo *helper = NULL;
6028         TnyList *list_to_move;
6029
6030         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6031
6032 #ifndef MODEST_TOOLKIT_HILDON2
6033         /* Get the main window if exists */
6034         ModestMainWindow *main_window;
6035         if (MODEST_IS_MAIN_WINDOW (win))
6036                 main_window = MODEST_MAIN_WINDOW (win);
6037         else
6038                 main_window =
6039                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6040                                                                                FALSE)); /* don't create */
6041 #endif
6042
6043         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6044
6045         if (!list_to_move)
6046                 return FALSE;
6047
6048         if (tny_list_get_length (list_to_move) < 1) {
6049                 g_object_unref (list_to_move);
6050                 return FALSE;
6051         }
6052
6053         /* Create and run the dialog */
6054         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6055         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6056                                      GTK_WINDOW (dialog),
6057                                      (GtkWindow *) win);
6058
6059         /* Create helper */
6060         helper = g_slice_new0 (MoveToInfo);
6061         helper->list = list_to_move;
6062         helper->win = win;
6063
6064         /* Listen to response signal */
6065         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6066
6067         /* Show the dialog */
6068         gtk_widget_show (dialog);
6069
6070         return FALSE;
6071 }
6072
6073 /*
6074  * Calls #HeadersFunc for each header already selected in the main
6075  * window or the message currently being shown in the msg view window
6076  */
6077 static void
6078 do_headers_action (ModestWindow *win,
6079                    HeadersFunc func,
6080                    gpointer user_data)
6081 {
6082         TnyList *headers_list = NULL;
6083         TnyIterator *iter = NULL;
6084         TnyHeader *header = NULL;
6085         TnyFolder *folder = NULL;
6086
6087         /* Get headers */
6088         headers_list = get_selected_headers (win);
6089         if (!headers_list)
6090                 return;
6091
6092         /* Get the folder */
6093         iter = tny_list_create_iterator (headers_list);
6094         header = TNY_HEADER (tny_iterator_get_current (iter));
6095         if (header) {
6096                 folder = tny_header_get_folder (header);
6097                 g_object_unref (header);
6098         }
6099
6100         /* Call the function for each header */
6101         while (!tny_iterator_is_done (iter)) {
6102                 header = TNY_HEADER (tny_iterator_get_current (iter));
6103                 func (header, win, user_data);
6104                 g_object_unref (header);
6105                 tny_iterator_next (iter);
6106         }
6107
6108         /* Trick: do a poke status in order to speed up the signaling
6109            of observers */
6110         if (folder) {
6111                 tny_folder_poke_status (folder);
6112                 g_object_unref (folder);
6113         }
6114
6115         /* Frees */
6116         g_object_unref (iter);
6117         g_object_unref (headers_list);
6118 }
6119
6120 void
6121 modest_ui_actions_view_attachment (GtkAction *action,
6122                                    ModestWindow *window)
6123 {
6124         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6125                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6126         } else {
6127                 /* not supported window for this action */
6128                 g_return_if_reached ();
6129         }
6130 }
6131
6132 void
6133 modest_ui_actions_save_attachments (GtkAction *action,
6134                                     ModestWindow *window)
6135 {
6136         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6137
6138                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6139                         return;
6140
6141                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6142         } else {
6143                 /* not supported window for this action */
6144                 g_return_if_reached ();
6145         }
6146 }
6147
6148 void
6149 modest_ui_actions_remove_attachments (GtkAction *action,
6150                                       ModestWindow *window)
6151 {
6152         if (MODEST_IS_MAIN_WINDOW (window)) {
6153                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6154         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6155                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6156         } else {
6157                 /* not supported window for this action */
6158                 g_return_if_reached ();
6159         }
6160 }
6161
6162 void
6163 modest_ui_actions_on_settings (GtkAction *action,
6164                                ModestWindow *win)
6165 {
6166         GtkWidget *dialog;
6167
6168         dialog = modest_platform_get_global_settings_dialog ();
6169         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6170         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6171         gtk_widget_show_all (dialog);
6172
6173         gtk_dialog_run (GTK_DIALOG (dialog));
6174
6175         gtk_widget_destroy (dialog);
6176 }
6177
6178 void
6179 modest_ui_actions_on_help (GtkAction *action,
6180                            GtkWindow *win)
6181 {
6182         /* Help app is not available at all in fremantle */
6183 #ifndef MODEST_TOOLKIT_HILDON2
6184         const gchar *help_id;
6185
6186         g_return_if_fail (win && GTK_IS_WINDOW(win));
6187
6188         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6189
6190         if (help_id)
6191                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6192 #endif
6193 }
6194
6195 void
6196 modest_ui_actions_on_csm_help (GtkAction *action,
6197                                GtkWindow *win)
6198 {
6199         /* Help app is not available at all in fremantle */
6200 #ifndef MODEST_TOOLKIT_HILDON2
6201
6202         const gchar* help_id = NULL;
6203         GtkWidget *folder_view;
6204         TnyFolderStore *folder_store;
6205
6206         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6207
6208         /* Get selected folder */
6209         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6210                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6211         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6212
6213         /* Switch help_id */
6214         if (folder_store && TNY_IS_FOLDER (folder_store))
6215                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6216
6217         if (folder_store)
6218                 g_object_unref (folder_store);
6219
6220         if (help_id)
6221                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6222         else
6223                 modest_ui_actions_on_help (action, win);
6224 #endif
6225 }
6226
6227 static void
6228 retrieve_contents_cb (ModestMailOperation *mail_op,
6229                       TnyHeader *header,
6230                       gboolean canceled,
6231                       TnyMsg *msg,
6232                       GError *err,
6233                       gpointer user_data)
6234 {
6235         /* We only need this callback to show an error in case of
6236            memory low condition */
6237         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6238                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6239         }
6240 }
6241
6242 static void
6243 retrieve_msg_contents_performer (gboolean canceled,
6244                                  GError *err,
6245                                  GtkWindow *parent_window,
6246                                  TnyAccount *account,
6247                                  gpointer user_data)
6248 {
6249         ModestMailOperation *mail_op;
6250         TnyList *headers = TNY_LIST (user_data);
6251
6252         if (err || canceled) {
6253                 check_memory_full_error ((GtkWidget *) parent_window, err);
6254                 goto out;
6255         }
6256
6257         /* Create mail operation */
6258         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6259                                                                  modest_ui_actions_disk_operations_error_handler,
6260                                                                  NULL, NULL);
6261         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6262         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6263
6264         /* Frees */
6265         g_object_unref (mail_op);
6266  out:
6267         g_object_unref (headers);
6268         g_object_unref (account);
6269 }
6270
6271 void
6272 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6273                                             ModestWindow *window)
6274 {
6275         TnyList *headers = NULL;
6276         TnyAccount *account = NULL;
6277         TnyIterator *iter = NULL;
6278         TnyHeader *header = NULL;
6279         TnyFolder *folder = NULL;
6280
6281         /* Get headers */
6282         headers = get_selected_headers (window);
6283         if (!headers)
6284                 return;
6285
6286         /* Pick the account */
6287         iter = tny_list_create_iterator (headers);
6288         header = TNY_HEADER (tny_iterator_get_current (iter));
6289         folder = tny_header_get_folder (header);
6290         account = tny_folder_get_account (folder);
6291         g_object_unref (folder);
6292         g_object_unref (header);
6293         g_object_unref (iter);
6294
6295         /* Connect and perform the message retrieval */
6296         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6297                                              g_object_ref (account),
6298                                              retrieve_msg_contents_performer,
6299                                              g_object_ref (headers));
6300
6301         /* Frees */
6302         g_object_unref (account);
6303         g_object_unref (headers);
6304 }
6305
6306 void
6307 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6308 {
6309         g_return_if_fail (MODEST_IS_WINDOW (window));
6310
6311         /* Update dimmed */
6312         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6313 }
6314
6315 void
6316 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6317 {
6318         g_return_if_fail (MODEST_IS_WINDOW (window));
6319
6320         /* Update dimmed */
6321         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6322 }
6323
6324 void
6325 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6326                                           ModestWindow *window)
6327 {
6328         g_return_if_fail (MODEST_IS_WINDOW (window));
6329
6330         /* Update dimmed */
6331         modest_ui_actions_check_menu_dimming_rules (window);
6332 }
6333
6334 void
6335 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6336                                           ModestWindow *window)
6337 {
6338         g_return_if_fail (MODEST_IS_WINDOW (window));
6339
6340         /* Update dimmed */
6341         modest_ui_actions_check_menu_dimming_rules (window);
6342 }
6343
6344 void
6345 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6346                                           ModestWindow *window)
6347 {
6348         g_return_if_fail (MODEST_IS_WINDOW (window));
6349
6350         /* Update dimmed */
6351         modest_ui_actions_check_menu_dimming_rules (window);
6352 }
6353
6354 void
6355 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6356                                             ModestWindow *window)
6357 {
6358         g_return_if_fail (MODEST_IS_WINDOW (window));
6359
6360         /* Update dimmed */
6361         modest_ui_actions_check_menu_dimming_rules (window);
6362 }
6363
6364 void
6365 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6366                                           ModestWindow *window)
6367 {
6368         g_return_if_fail (MODEST_IS_WINDOW (window));
6369
6370         /* Update dimmed */
6371         modest_ui_actions_check_menu_dimming_rules (window);
6372 }
6373
6374 void
6375 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6376                                           ModestWindow *window)
6377 {
6378         g_return_if_fail (MODEST_IS_WINDOW (window));
6379
6380         /* Update dimmed */
6381         modest_ui_actions_check_menu_dimming_rules (window);
6382 }
6383
6384 void
6385 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6386                                                  ModestWindow *window)
6387 {
6388         g_return_if_fail (MODEST_IS_WINDOW (window));
6389
6390         /* Update dimmed */
6391         modest_ui_actions_check_menu_dimming_rules (window);
6392 }
6393
6394 void
6395 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6396                                                      ModestWindow *window)
6397 {
6398         g_return_if_fail (MODEST_IS_WINDOW (window));
6399
6400         /* Update dimmed */
6401         modest_ui_actions_check_menu_dimming_rules (window);
6402 }
6403
6404 void
6405 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6406                                                      ModestWindow *window)
6407 {
6408         g_return_if_fail (MODEST_IS_WINDOW (window));
6409
6410         /* Update dimmed */
6411         modest_ui_actions_check_menu_dimming_rules (window);
6412 }
6413
6414 void
6415 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6416 {
6417         g_return_if_fail (MODEST_IS_WINDOW (window));
6418
6419         /* we check for low-mem; in that case, show a warning, and don't allow
6420          * searching
6421          */
6422         if (modest_platform_check_memory_low (window, TRUE))
6423                 return;
6424
6425         modest_platform_show_search_messages (GTK_WINDOW (window));
6426 }
6427
6428 void
6429 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6430 {
6431         g_return_if_fail (MODEST_IS_WINDOW (win));
6432
6433
6434         /* we check for low-mem; in that case, show a warning, and don't allow
6435          * for the addressbook
6436          */
6437         if (modest_platform_check_memory_low (win, TRUE))
6438                 return;
6439
6440
6441         modest_platform_show_addressbook (GTK_WINDOW (win));
6442 }
6443
6444
6445 void
6446 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6447                                           ModestWindow *window)
6448 {
6449         gboolean active;
6450         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6451
6452         if (GTK_IS_TOGGLE_ACTION (action))
6453                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6454         else
6455                 active = TRUE;
6456
6457         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6458                                                     active);
6459 }
6460
6461 static void
6462 on_send_receive_finished (ModestMailOperation  *mail_op,
6463                            gpointer user_data)
6464 {
6465         GtkWidget *header_view, *folder_view;
6466         TnyFolderStore *folder_store;
6467         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6468
6469         /* Set send/receive operation finished */
6470         modest_main_window_notify_send_receive_completed (main_win);
6471
6472         /* Don't refresh the current folder if there were any errors */
6473         if (modest_mail_operation_get_status (mail_op) !=
6474             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6475                 return;
6476
6477         /* Refresh the current folder if we're viewing a window. We do
6478            this because the user won't be able to see the new mails in
6479            the selected folder after a Send&Receive because it only
6480            performs a poke_status, i.e, only the number of read/unread
6481            messages is updated, but the new headers are not
6482            downloaded */
6483         folder_view = modest_main_window_get_child_widget (main_win,
6484                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6485         if (!folder_view)
6486                 return;
6487
6488         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6489
6490         /* Do not need to refresh INBOX again because the
6491            update_account does it always automatically */
6492         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6493             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6494                 ModestMailOperation *refresh_op;
6495
6496                 header_view = modest_main_window_get_child_widget (main_win,
6497                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6498
6499                 /* We do not need to set the contents style
6500                    because it hasn't changed. We also do not
6501                    need to save the widget status. Just force
6502                    a refresh */
6503                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6504                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6505                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6506                                                       folder_refreshed_cb, main_win);
6507                 g_object_unref (refresh_op);
6508         }
6509
6510         if (folder_store)
6511                 g_object_unref (folder_store);
6512 }
6513
6514
6515 void
6516 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6517                                                 TnyHeader *header,
6518                                                 TnyMsg *msg,
6519                                                 GError *err,
6520                                                 gpointer user_data)
6521 {
6522         const gchar* server_name = NULL;
6523         TnyTransportAccount *transport;
6524         gchar *message = NULL;
6525         ModestProtocol *protocol;
6526
6527         /* Don't show anything if the user cancelled something or the
6528          * send receive request is not interactive. Authentication
6529          * errors are managed by the account store so no need to show
6530          * a dialog here again */
6531         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6532             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6533             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6534                 return;
6535
6536
6537         /* Get the server name. Note that we could be using a
6538            connection specific transport account */
6539         transport = (TnyTransportAccount *)
6540                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6541         if (transport) {
6542                 ModestTnyAccountStore *acc_store;
6543                 const gchar *acc_name;
6544                 TnyTransportAccount *conn_specific;
6545
6546                 acc_store = modest_runtime_get_account_store();
6547                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6548                 conn_specific = (TnyTransportAccount *)
6549                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6550                 if (conn_specific) {
6551                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6552                         g_object_unref (conn_specific);
6553                 } else {
6554                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6555                 }
6556                 g_object_unref (transport);
6557         }
6558
6559         /* Get protocol */
6560         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6561                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6562                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6563         if (!protocol) {
6564                 g_warning ("%s: Account with no proto", __FUNCTION__);
6565                 return;
6566         }
6567
6568         /* Show the appropriate message text for the GError: */
6569         switch (err->code) {
6570         case TNY_SERVICE_ERROR_CONNECT:
6571                 message = modest_protocol_get_translation (protocol,
6572                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6573                                                            server_name);
6574                 break;
6575         case TNY_SERVICE_ERROR_SEND:
6576                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6577                 break;
6578         case TNY_SERVICE_ERROR_UNAVAILABLE:
6579                 message = modest_protocol_get_translation (protocol,
6580                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6581                                                            server_name);
6582                 break;
6583         default:
6584                 g_warning ("%s: unexpected ERROR %d",
6585                            __FUNCTION__, err->code);
6586                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6587                 break;
6588         }
6589
6590         modest_platform_run_information_dialog (NULL, message, FALSE);
6591         g_free (message);
6592 }
6593
6594 void
6595 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6596                                                 gchar *msg_id,
6597                                                 guint status,
6598                                                 gpointer user_data)
6599 {
6600         ModestWindow *top_window = NULL;
6601         ModestWindowMgr *mgr = NULL;
6602         GtkWidget *header_view = NULL;
6603         TnyFolder *selected_folder = NULL;
6604         TnyFolderType folder_type;
6605
6606         mgr = modest_runtime_get_window_mgr ();
6607         top_window = modest_window_mgr_get_current_top (mgr);
6608
6609         if (!top_window)
6610                 return;
6611
6612 #ifndef MODEST_TOOLKIT_HILDON2
6613         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6614                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6615                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6616         }
6617 #else
6618         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6619                 header_view = (GtkWidget *)
6620                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6621         }
6622 #endif
6623
6624         /* Get selected folder */
6625         if (header_view)
6626                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6627         if (!selected_folder)
6628                 return;
6629
6630         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6631 #if GTK_CHECK_VERSION(2, 8, 0)
6632         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6633         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6634                 GtkTreeViewColumn *tree_column;
6635
6636                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6637                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6638                 if (tree_column)
6639                         gtk_tree_view_column_queue_resize (tree_column);
6640                 }
6641 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6642         gtk_widget_queue_draw (header_view);
6643 #endif
6644
6645 #ifndef MODEST_TOOLKIT_HILDON2
6646         /* Rerun dimming rules, because the message could become deletable for example */
6647         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6648                                                  MODEST_DIMMING_RULES_TOOLBAR);
6649         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6650                                                  MODEST_DIMMING_RULES_MENU);
6651 #endif
6652
6653         /* Free */
6654         g_object_unref (selected_folder);
6655 }
6656
6657 void
6658 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6659                                                TnyAccount *account)
6660 {
6661         ModestProtocolType protocol_type;
6662         ModestProtocol *protocol;
6663         gchar *error_note = NULL;
6664
6665         protocol_type = modest_tny_account_get_protocol_type (account);
6666         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6667                                                                   protocol_type);
6668
6669         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6670         if (error_note == NULL) {
6671                 g_warning ("%s: This should not be reached", __FUNCTION__);
6672         } else {
6673                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6674                 g_free (error_note);
6675         }
6676 }
6677
6678 gchar *
6679 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6680 {
6681         gchar *msg = NULL;
6682         gchar *subject;
6683         TnyFolderStore *folder = NULL;
6684         TnyAccount *account = NULL;
6685         ModestProtocolType proto;
6686         ModestProtocol *protocol;
6687         TnyHeader *header = NULL;
6688
6689         if (MODEST_IS_MAIN_WINDOW (win)) {
6690                 GtkWidget *header_view;
6691                 TnyList* headers = NULL;
6692                 TnyIterator *iter;
6693                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6694                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6695                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6696                 if (!headers || tny_list_get_length (headers) == 0) {
6697                         if (headers)
6698                                 g_object_unref (headers);
6699                         return NULL;
6700                 }
6701                 iter = tny_list_create_iterator (headers);
6702                 header = TNY_HEADER (tny_iterator_get_current (iter));
6703                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6704                 g_object_unref (iter);
6705                 g_object_unref (headers);
6706 #ifdef MODEST_TOOLKIT_HILDON2
6707         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6708                 GtkWidget *header_view;
6709                 TnyList* headers = NULL;
6710                 TnyIterator *iter;
6711                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6712                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6713                 if (!headers || tny_list_get_length (headers) == 0) {
6714                         if (headers)
6715                                 g_object_unref (headers);
6716                         return NULL;
6717                 }
6718                 iter = tny_list_create_iterator (headers);
6719                 header = TNY_HEADER (tny_iterator_get_current (iter));
6720                 if (header) {
6721                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6722                 } else {
6723                         g_warning ("List should contain headers");
6724                 }
6725                 g_object_unref (iter);
6726                 g_object_unref (headers);
6727 #endif
6728         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6729                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6730                 if (header)
6731                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6732         }
6733
6734         if (!header || !folder)
6735                 goto frees;
6736
6737         /* Get the account type */
6738         account = tny_folder_get_account (TNY_FOLDER (folder));
6739         proto = modest_tny_account_get_protocol_type (account);
6740         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6741                                                                   proto);
6742
6743         subject = tny_header_dup_subject (header);
6744         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6745         if (subject)
6746                 g_free (subject);
6747         if (msg == NULL) {
6748                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6749         }
6750
6751  frees:
6752         /* Frees */
6753         if (account)
6754                 g_object_unref (account);
6755         if (folder)
6756                 g_object_unref (folder);
6757         if (header)
6758                 g_object_unref (header);
6759
6760         return msg;
6761 }
6762
6763 gboolean
6764 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6765                                      const gchar *account_name,
6766                                      const gchar *account_title)
6767 {
6768         ModestAccountMgr *account_mgr;
6769         gchar *txt = NULL;
6770         gint response;
6771         ModestProtocol *protocol;
6772         gboolean removed = FALSE;
6773
6774         g_return_val_if_fail (account_name, FALSE);
6775         g_return_val_if_fail (account_title, FALSE);
6776
6777         account_mgr = modest_runtime_get_account_mgr();
6778
6779         /* The warning text depends on the account type: */
6780         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6781                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6782                                                                                                          account_name));
6783         txt = modest_protocol_get_translation (protocol,
6784                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6785                                                account_title);
6786         if (txt == NULL)
6787                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6788
6789         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6790         g_free (txt);
6791         txt = NULL;
6792
6793         if (response == GTK_RESPONSE_OK) {
6794                 /* Remove account. If it succeeds then it also removes
6795                    the account from the ModestAccountView: */
6796                 gboolean is_default = FALSE;
6797                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6798                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6799                         is_default = TRUE;
6800                 g_free (default_account_name);
6801
6802                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6803                 if (!removed)
6804                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6805         }
6806         return removed;
6807 }
6808
6809 void 
6810 modest_ui_actions_on_fetch_images (GtkAction *action,
6811                                    ModestWindow *window)
6812 {
6813         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6814
6815         modest_msg_view_window_fetch_images (MODEST_MSG_VIEW_WINDOW (window));
6816
6817 }
6818
6819 void
6820 modest_ui_actions_on_reload_message (const gchar *msg_id)
6821 {
6822         ModestWindow *window = NULL;
6823
6824         g_return_if_fail (msg_id && msg_id[0] != '\0');
6825         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6826                                                             msg_id,
6827                                                             &window))
6828                 return;
6829
6830
6831         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6832                 return;
6833
6834         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6835 }