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