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