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