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