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