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