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