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