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