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