Bugfix for 81611
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard-dialog.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 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 (TnyFolderStore *folder);
158
159 static void     do_create_folder (GtkWindow *window, 
160                                   TnyFolderStore *parent_folder, 
161                                   const gchar *suggested_name);
162
163 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
164
165 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
166
167 static void transfer_messages_helper (GtkWindow *win,
168                                       TnyFolder *src_folder,
169                                       TnyList *headers,
170                                       TnyFolder *dst_folder);
171
172 /*
173  * This function checks whether a TnyFolderStore is a pop account
174  */
175 static gboolean
176 remote_folder_is_pop (TnyFolderStore *folder)
177 {
178         const gchar *proto = NULL;
179         TnyAccount *account = NULL;
180
181         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
182         
183         account = get_account_from_folder_store (folder);
184         proto = tny_account_get_proto (account);
185         g_object_unref (account);
186
187         return (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
188 }
189
190 /* FIXME: this should be merged with the similar code in modest-account-view-window */
191 /* Show the account creation wizard dialog.
192  * returns: TRUE if an account was created. FALSE if the user cancelled.
193  */
194 gboolean
195 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
196 {
197         gboolean result = FALSE;        
198         GtkWindow *dialog, *wizard;
199         gint dialog_response;
200
201         /* Show the easy-setup wizard: */       
202         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
203         if (dialog) {
204                 /* old wizard is active already; 
205                  */
206                 gtk_window_present (GTK_WINDOW(dialog));
207                 return FALSE;
208         }
209         
210
211         /* there is no such wizard yet */       
212         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
213         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
214
215         /* always present a main window in the background 
216          * we do it here, so we cannot end up with two wizards (as this
217          * function might be called in modest_window_mgr_get_main_window as well */
218         if (!win) 
219                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
220                                                          TRUE);  /* create if not existent */
221         
222         /* make sure the mainwindow is visible */
223         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
224         gtk_widget_show_all (GTK_WIDGET(win));
225         gtk_window_present (GTK_WINDOW(win));
226         
227         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
228         gtk_widget_destroy (GTK_WIDGET (wizard));
229         if (gtk_events_pending ())
230                 gtk_main_iteration ();
231
232         if (dialog_response == GTK_RESPONSE_CANCEL) {
233                 result = FALSE;
234         } else {
235                 /* Check whether an account was created: */
236                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
237         }
238         return result;
239 }
240
241
242 void   
243 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
244 {
245         GtkWidget *about;
246         const gchar *authors[] = {
247                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
248                 NULL
249         };
250         about = gtk_about_dialog_new ();
251         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
252         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
253         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
254                                         _("Copyright (c) 2006, Nokia Corporation\n"
255                                           "All rights reserved."));
256         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
257                                        _("a modest e-mail client\n\n"
258                                          "design and implementation: Dirk-Jan C. Binnema\n"
259                                          "contributions from the fine people at KC and Ig\n"
260                                          "uses the tinymail email framework written by Philip van Hoof"));
261         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
262         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
263         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
264         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
265         
266         gtk_dialog_run (GTK_DIALOG (about));
267         gtk_widget_destroy(about);
268 }
269
270 /*
271  * Gets the list of currently selected messages. If the win is the
272  * main window, then it returns a newly allocated list of the headers
273  * selected in the header view. If win is the msg view window, then
274  * the value returned is a list with just a single header.
275  *
276  * The caller of this funcion must free the list.
277  */
278 static TnyList *
279 get_selected_headers (ModestWindow *win)
280 {
281         if (MODEST_IS_MAIN_WINDOW(win)) {
282                 GtkWidget *header_view;         
283                 
284                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
285                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
286                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
287                 
288         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
289                 /* for MsgViewWindows, we simply return a list with one element */
290                 TnyHeader *header;
291                 TnyList *list = NULL;
292                 
293                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
294                 if (header != NULL) {
295                         list = tny_simple_list_new ();
296                         tny_list_prepend (list, G_OBJECT(header));
297                         g_object_unref (G_OBJECT(header));
298                 }
299
300                 return list;
301
302         } else
303                 return NULL;
304 }
305
306 static GtkTreeRowReference *
307 get_next_after_selected_headers (ModestHeaderView *header_view)
308 {
309         GtkTreeSelection *sel;
310         GList *selected_rows, *node;
311         GtkTreePath *path;
312         GtkTreeRowReference *result;
313         GtkTreeModel *model;
314
315         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
316         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
317         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
318
319         if (selected_rows == NULL)
320                 return NULL;
321
322         node = g_list_last (selected_rows);
323         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
324         gtk_tree_path_next (path);
325
326         result = gtk_tree_row_reference_new (model, path);
327
328         gtk_tree_path_free (path);
329         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
330         g_list_free (selected_rows);
331
332         return result;
333 }
334
335 static void
336 headers_action_mark_as_read (TnyHeader *header,
337                              ModestWindow *win,
338                              gpointer user_data)
339 {
340         TnyHeaderFlags flags;
341
342         g_return_if_fail (TNY_IS_HEADER(header));
343
344         flags = tny_header_get_flags (header);
345         if (flags & TNY_HEADER_FLAG_SEEN) return;
346         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
347 }
348
349 static void
350 headers_action_mark_as_unread (TnyHeader *header,
351                                ModestWindow *win,
352                                gpointer user_data)
353 {
354         TnyHeaderFlags flags;
355
356         g_return_if_fail (TNY_IS_HEADER(header));
357
358         flags = tny_header_get_flags (header);
359         if (flags & TNY_HEADER_FLAG_SEEN)  {
360                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
361         }
362 }
363
364 /** After deleing a message that is currently visible in a window, 
365  * show the next message from the list, or close the window if there are no more messages.
366  **/
367 void 
368 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
369 {
370         /* Close msg view window or select next */
371         if (!modest_msg_view_window_select_next_message (win) &&
372             !modest_msg_view_window_select_previous_message (win)) {
373                 gboolean ret_value;
374                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
375         }
376 }
377
378
379 void
380 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
381 {
382         TnyList *header_list = NULL;
383         TnyIterator *iter = NULL;
384         TnyHeader *header = NULL;
385         gchar *message = NULL;
386         gchar *desc = NULL;
387         gint response;
388         ModestWindowMgr *mgr;
389         GtkWidget *header_view = NULL;
390
391         g_return_if_fail (MODEST_IS_WINDOW(win));
392         
393         /* Check first if the header view has the focus */
394         if (MODEST_IS_MAIN_WINDOW (win)) {
395                 header_view = 
396                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
397                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
398                 if (!gtk_widget_is_focus (header_view))
399                         return;
400         }
401         
402         /* Get the headers, either from the header view (if win is the main window),
403          * or from the message view window: */
404         header_list = get_selected_headers (win);
405         if (!header_list) return;
406                         
407         /* Check if any of the headers are already opened, or in the process of being opened */
408         if (MODEST_IS_MAIN_WINDOW (win)) {
409                 gint opened_headers = 0;
410
411                 iter = tny_list_create_iterator (header_list);
412                 mgr = modest_runtime_get_window_mgr ();
413                 while (!tny_iterator_is_done (iter)) {
414                         header = TNY_HEADER (tny_iterator_get_current (iter));
415                         if (header) {
416                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
417                                         opened_headers++;
418                                 g_object_unref (header);
419                         }
420                         tny_iterator_next (iter);
421                 }
422                 g_object_unref (iter);
423
424                 if (opened_headers > 0) {
425                         gchar *msg;
426
427                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
428                                                opened_headers);
429
430                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
431                         
432                         g_free (msg);
433                         g_object_unref (header_list);
434                         return;
435                 }
436         }
437
438         /* Select message */
439         if (tny_list_get_length(header_list) == 1) {
440                 iter = tny_list_create_iterator (header_list);
441                 header = TNY_HEADER (tny_iterator_get_current (iter));
442                 if (header) {
443                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
444                         g_object_unref (header);
445                 }
446
447                 g_object_unref (iter);
448         }
449         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
450                                            tny_list_get_length(header_list)), desc);
451
452         /* Confirmation dialog */
453         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
454                                                             message);
455         
456
457         if (response == GTK_RESPONSE_OK) {      
458                 ModestWindow *main_window = NULL;
459                 ModestWindowMgr *mgr = NULL;
460                 GtkTreeModel *model = NULL;
461                 GtkTreeSelection *sel = NULL;
462                 GList *sel_list = NULL, *tmp = NULL;
463                 GtkTreeRowReference *next_row_reference = NULL;
464                 GtkTreeRowReference *prev_row_reference = NULL;
465                 GtkTreePath *next_path = NULL;
466                 GtkTreePath *prev_path = NULL;
467                 ModestMailOperation *mail_op = NULL;
468
469                 /* Find last selected row */                    
470                 if (MODEST_IS_MAIN_WINDOW (win)) {
471                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
472                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
473                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
474                         for (tmp=sel_list; tmp; tmp=tmp->next) {
475                                 if (tmp->next == NULL) {
476                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
477                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
478
479                                         gtk_tree_path_prev (prev_path);
480                                         gtk_tree_path_next (next_path);
481
482                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
483                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
484                                 }
485                         }
486                 }
487                 
488                 /* Disable window dimming management */
489                 modest_window_disable_dimming (MODEST_WINDOW(win));
490
491                 /* Remove each header. If it's a view window header_view == NULL */
492                 mail_op = modest_mail_operation_new ((GObject *) win);
493                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
494                                                  mail_op);
495                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
496                 g_object_unref (mail_op);
497                 
498                 /* Enable window dimming management */
499                 if (sel != NULL) {
500                         gtk_tree_selection_unselect_all (sel);
501                 }
502                 modest_window_enable_dimming (MODEST_WINDOW(win));
503                 
504                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
505                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
506                         
507                         /* Get main window */
508                         mgr = modest_runtime_get_window_mgr ();
509                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
510                 } else {                        
511                         /* Move cursor to next row */
512                         main_window = win; 
513
514                         /* Select next or previous row */
515                         if (gtk_tree_row_reference_valid (next_row_reference)) {
516 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
517                                 gtk_tree_selection_select_path (sel, next_path);
518                         }
519                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
520                                 gtk_tree_selection_select_path (sel, prev_path);
521                         }
522
523                         /* Free */
524                         if (next_row_reference != NULL) 
525                                 gtk_tree_row_reference_free (next_row_reference);
526                         if (next_path != NULL) 
527                                 gtk_tree_path_free (next_path);                         
528                         if (prev_row_reference != NULL) 
529                                 gtk_tree_row_reference_free (prev_row_reference);
530                         if (prev_path != NULL) 
531                                 gtk_tree_path_free (prev_path);                         
532                 }
533                 
534                 /* Update toolbar dimming state */
535                 if (main_window)
536                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
537
538                 /* Free */
539                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
540                 g_list_free (sel_list);
541         }
542
543         /* Free*/
544         g_free(message);
545         g_free(desc);
546         g_object_unref (header_list);
547 }
548
549
550
551
552 /* delete either message or folder, based on where we are */
553 void
554 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
555 {
556         g_return_if_fail (MODEST_IS_WINDOW(win));
557         
558         /* Check first if the header view has the focus */
559         if (MODEST_IS_MAIN_WINDOW (win)) {
560                 GtkWidget *w;
561                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
562                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
563                 if (gtk_widget_is_focus (w)) {
564                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
565                         return;
566                 }
567         }
568         modest_ui_actions_on_delete_message (action, win);
569 }
570
571 void
572 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
573 {       
574         ModestWindowMgr *mgr = NULL;
575         
576 #ifdef MODEST_PLATFORM_MAEMO
577         modest_osso_save_state();
578 #endif /* MODEST_PLATFORM_MAEMO */
579
580         g_debug ("closing down, clearing %d item(s) from operation queue",
581                  modest_mail_operation_queue_num_elements
582                  (modest_runtime_get_mail_operation_queue()));
583
584         /* cancel all outstanding operations */
585         modest_mail_operation_queue_cancel_all 
586                 (modest_runtime_get_mail_operation_queue());
587         
588         g_debug ("queue has been cleared");
589
590
591         /* Check if there are opened editing windows */ 
592         mgr = modest_runtime_get_window_mgr ();
593         modest_window_mgr_close_all_windows (mgr);
594
595         /* note: when modest-tny-account-store is finalized,
596            it will automatically set all network connections
597            to offline */
598
599 /*      gtk_main_quit (); */
600 }
601
602 void
603 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
604 {
605         gboolean ret_value;
606
607         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
608
609 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
610 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
611 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
612 /*              gboolean ret_value; */
613 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
614 /*      } else if (MODEST_IS_WINDOW (win)) { */
615 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
616 /*      } else { */
617 /*              g_return_if_reached (); */
618 /*      } */
619 }
620
621 void
622 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
623 {
624         GtkClipboard *clipboard = NULL;
625         gchar *selection = NULL;
626
627         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
628         selection = gtk_clipboard_wait_for_text (clipboard);
629
630         /* Question: why is the clipboard being used here? 
631          * It doesn't really make a lot of sense. */
632
633         if (selection)
634         {
635                 modest_address_book_add_address (selection);
636                 g_free (selection);
637         }
638 }
639
640 void
641 modest_ui_actions_on_accounts (GtkAction *action, 
642                                ModestWindow *win)
643 {
644         /* This is currently only implemented for Maemo */
645         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
646                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
647                         g_debug ("%s: wizard was already running", __FUNCTION__);
648                 
649                 return;
650         } else {
651                 /* Show the list of accounts */
652                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
653                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
654                 
655                 /* The accounts dialog must be modal */
656                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
657                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
658         }
659 }
660
661 #ifdef MODEST_PLATFORM_MAEMO
662 static void
663 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
664 {
665         /* Save any changes. */
666         modest_connection_specific_smtp_window_save_server_accounts (
667                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
668         gtk_widget_destroy (GTK_WIDGET (window));
669 }
670 #endif
671
672
673 void
674 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
675 {
676         /* This is currently only implemented for Maemo,
677          * because it requires an API (libconic) to detect different connection 
678          * possiblities.
679          */
680 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
681         
682         /* Create the window if necessary: */
683         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
684         modest_connection_specific_smtp_window_fill_with_connections (
685                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
686                 modest_runtime_get_account_mgr());
687
688         /* Show the window: */  
689         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
690         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
691         gtk_widget_show (specific_window);
692     
693         /* Save changes when the window is hidden: */
694         g_signal_connect (specific_window, "hide", 
695                 G_CALLBACK (on_smtp_servers_window_hide), win);
696 #endif /* MODEST_PLATFORM_MAEMO */
697 }
698
699 void
700 modest_ui_actions_compose_msg(ModestWindow *win,
701                               const gchar *to_str,
702                               const gchar *cc_str,
703                               const gchar *bcc_str,
704                               const gchar *subject_str,
705                               const gchar *body_str,
706                               GSList *attachments,
707                               gboolean set_as_modified)
708 {
709         gchar *account_name = NULL;
710         TnyMsg *msg = NULL;
711         TnyAccount *account = NULL;
712         TnyFolder *folder = NULL;
713         gchar *from_str = NULL, *signature = NULL, *body = NULL;
714         gboolean use_signature = FALSE;
715         ModestWindow *msg_win = NULL;
716         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
717         ModestTnyAccountStore *store = modest_runtime_get_account_store();
718
719         account_name = modest_account_mgr_get_default_account(mgr);
720         if (!account_name) {
721                 g_printerr ("modest: no account found\n");
722                 goto cleanup;
723         }
724         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
725         if (!account) {
726                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
727                 goto cleanup;
728         }
729         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
730         if (!folder) {
731                 g_printerr ("modest: failed to find Drafts folder\n");
732                 goto cleanup;
733         }
734         from_str = modest_account_mgr_get_from_string (mgr, account_name);
735         if (!from_str) {
736                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
737                 goto cleanup;
738         }
739
740         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
741         if (body_str != NULL) {
742                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
743         } else {
744                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
745         }
746
747         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
748         if (!msg) {
749                 g_printerr ("modest: failed to create new msg\n");
750                 goto cleanup;
751         }
752
753         /* Create and register edit window */
754         /* This is destroyed by TODO. */
755         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
756         while (attachments) {
757                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
758                                                        attachments->data);
759                 attachments = g_slist_next(attachments);
760         }
761         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
762         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
763
764         gtk_widget_show_all (GTK_WIDGET (msg_win));
765
766 cleanup:
767         g_free (from_str);
768         g_free (signature);
769         g_free (body);
770         g_free (account_name);
771         if (account) g_object_unref (G_OBJECT(account));
772         if (folder) g_object_unref (G_OBJECT(folder));
773         if (msg_win) g_object_unref (G_OBJECT(msg_win));
774         if (msg) g_object_unref (G_OBJECT(msg));
775 }
776
777 void
778 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
779 {
780         /* if there are no accounts yet, just show the wizard */
781         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
782                 if (!modest_ui_actions_run_account_setup_wizard (win))
783                         return;
784                 
785         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
786 }
787
788
789 gboolean 
790 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
791                                        TnyHeader *header,
792                                        TnyMsg *msg)
793 {
794         ModestMailOperationStatus status;
795
796         /* If there is no message or the operation was not successful */
797         status = modest_mail_operation_get_status (mail_op);
798         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
799
800                 /* Remove the header from the preregistered uids */
801                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
802                                                      header);
803
804                 return FALSE;
805         }
806
807         return TRUE;
808 }
809
810 typedef struct {
811         guint idle_handler;
812         gchar *message;
813         GtkWidget *banner;
814 } OpenMsgBannerInfo;
815
816 gboolean
817 open_msg_banner_idle (gpointer userdata)
818 {
819         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
820
821         gdk_threads_enter ();
822         banner_info->idle_handler = 0;
823         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
824         g_object_ref (banner_info->banner);
825         
826         gdk_threads_leave ();
827
828         return FALSE;
829         
830 }
831
832 static void
833 open_msg_cb (ModestMailOperation *mail_op, 
834              TnyHeader *header,  
835              gboolean canceled,
836              TnyMsg *msg, 
837              GError *err,
838              gpointer user_data)
839 {
840         ModestWindowMgr *mgr = NULL;
841         ModestWindow *parent_win = NULL;
842         ModestWindow *win = NULL;
843         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
844         gchar *account = NULL;
845         TnyFolder *folder;
846         gboolean open_in_editor = FALSE;
847         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) user_data;
848         
849         /* Do nothing if there was any problem with the mail
850            operation. The error will be shown by the error_handler of
851            the mail operation */
852         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
853                 goto banner_cleanup;
854
855         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
856         folder = tny_header_get_folder (header);
857
858         /* Mark header as read */
859         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
860
861         /* Gets folder type (OUTBOX headers will be opened in edit window */
862         if (modest_tny_folder_is_local_folder (folder)) {
863                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
864                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
865                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
866         }
867
868                 
869         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
870                 TnyTransportAccount *traccount = NULL;
871                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
872                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
873                 if (traccount) {
874                         ModestTnySendQueue *send_queue = NULL;
875                         ModestTnySendQueueStatus status;
876                         char *msg_id;
877                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
878                                                    TNY_ACCOUNT(traccount)));
879                         send_queue = modest_runtime_get_send_queue(traccount);
880                         msg_id = modest_tny_send_queue_get_msg_id (header);
881                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
882                         /* Only open messages in outbox with the editor if they are in Failed state */
883                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
884                                 open_in_editor = TRUE;
885                         }
886                         g_free(msg_id);
887                         g_object_unref(traccount);
888                 } else {
889                         g_warning("Cannot get transport account for message in outbox!!");
890                 }
891         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
892                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
893         }
894
895         /* Get account */
896         if (!account)
897                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
898         if (!account)
899                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
900         
901         if (open_in_editor) {
902                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
903                 const gchar *from_header = NULL;
904
905                 from_header = tny_header_get_from (header);
906
907                 /* we cannot edit without a valid account... */
908                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
909                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
910                                 goto cleanup;
911                 }
912                 
913                 if (from_header) {
914                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
915                         GSList *node = NULL;
916                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
917                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
918                                 
919                                 if (from && (strcmp (from_header, from) == 0)) {
920                                         g_free (account);
921                                         account = g_strdup (node->data);
922                                         g_free (from);
923                                         break;
924                                 }
925                                 g_free (from);
926                         }
927                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
928                         g_slist_free (accounts);
929                 }
930
931                 win = modest_msg_edit_window_new (msg, account, TRUE);
932
933
934
935         } else {
936                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
937                 
938                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
939                         GtkWidget *header_view;
940                         GtkTreeSelection *sel;
941                         GList *sel_list = NULL;
942                         GtkTreeModel *model;
943                         
944                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
945                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
946
947                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
948                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
949
950                         if (sel_list != NULL) {
951                                 GtkTreeRowReference *row_reference;
952
953                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
954                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
955                                 g_list_free (sel_list);
956                                 
957                                 win = modest_msg_view_window_new_with_header_model (
958                                                 msg, account, (const gchar*) uid,
959                                                 model, row_reference);
960                                 gtk_tree_row_reference_free (row_reference);
961                         } else {
962                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
963                         }
964                 } else {
965                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
966                 }
967                 g_free (uid);
968         }
969         
970         /* Register and show new window */
971         if (win != NULL) {
972                 mgr = modest_runtime_get_window_mgr ();
973                 modest_window_mgr_register_window (mgr, win);
974                 g_object_unref (win);
975                 gtk_widget_show_all (GTK_WIDGET(win));
976         }
977
978         /* Update toolbar dimming state */
979         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
980                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
981         }
982
983 cleanup:
984         /* Free */
985         g_free(account);
986         g_object_unref (parent_win);
987         g_object_unref (folder);
988 banner_cleanup:
989         if (banner_info) {
990                 g_free (banner_info->message);
991                 if (banner_info->idle_handler > 0) {
992                         g_source_remove (banner_info->idle_handler);
993                         banner_info->idle_handler = 0;
994                 }
995                 if (banner_info->banner != NULL) {
996                         gtk_widget_destroy (banner_info->banner);
997                         g_object_unref (banner_info->banner);
998                         banner_info->banner = NULL;
999                 }
1000                 g_slice_free (OpenMsgBannerInfo, banner_info);
1001         }
1002 }
1003
1004 void
1005 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1006                                                gpointer user_data)
1007 {
1008         const GError *error;
1009         GObject *win = NULL;
1010
1011         win = modest_mail_operation_get_source (mail_op);
1012         error = modest_mail_operation_get_error (mail_op);
1013
1014         /* Show error */
1015         if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
1016             error->code == TNY_IO_ERROR_WRITE ||
1017             error->code == TNY_IO_ERROR_READ) {
1018                 ModestMailOperationStatus st = modest_mail_operation_get_status (mail_op);
1019                 /* If the mail op has been cancelled then it's not an error: don't show any message */
1020                 if (st != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1021                         modest_platform_information_banner ((GtkWidget *) win,
1022                                                             NULL, dgettext("ke-recv",
1023                                                                            "cerm_device_memory_full"));
1024                 }
1025         } else if (user_data) {
1026                 modest_platform_information_banner ((GtkWidget *) win, 
1027                                                     NULL, user_data);
1028         }
1029
1030         if (win)
1031                 g_object_unref (win);
1032 }
1033
1034 /**
1035  * Returns the account a list of headers belongs to. It returns a
1036  * *new* reference so don't forget to unref it
1037  */
1038 static TnyAccount*
1039 get_account_from_header_list (TnyList *headers)
1040 {
1041         TnyAccount *account = NULL;
1042
1043         if (tny_list_get_length (headers) > 0) {
1044                 TnyIterator *iter = tny_list_create_iterator (headers);
1045                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1046                 TnyFolder *folder = tny_header_get_folder (header);
1047                 
1048                 if (!folder) {
1049                         g_object_unref (header);
1050                         
1051                         while (!tny_iterator_is_done (iter)) {
1052                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1053                                 folder = tny_header_get_folder (header);
1054                                 if (folder) 
1055                                         break;
1056                                 g_object_unref (header);
1057                                 header = NULL;
1058                                 tny_iterator_next (iter);
1059                         }
1060                 }
1061
1062                 if (folder) {
1063                         account = tny_folder_get_account (folder);
1064                         g_object_unref (folder);
1065                 }
1066                 
1067                 if (header)
1068                         g_object_unref (header);
1069                 
1070                 g_object_unref (iter);
1071         }
1072         return account;
1073 }
1074
1075 static void 
1076 foreach_unregister_headers (gpointer data,
1077                             gpointer user_data)
1078 {
1079         ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1080         TnyHeader *header = TNY_HEADER (data);
1081
1082         modest_window_mgr_unregister_header (mgr, header);
1083 }
1084
1085 static void
1086 open_msgs_performer(gboolean canceled, 
1087                     GError *err,
1088                     GtkWindow *parent_window,
1089                     TnyAccount *account,
1090                     gpointer user_data)
1091 {
1092         ModestMailOperation *mail_op = NULL;
1093         const gchar *proto_name;
1094         gchar *error_msg;
1095         ModestTransportStoreProtocol proto;
1096         TnyList *not_opened_headers;
1097         TnyConnectionStatus status;
1098         gboolean show_open_draft = FALSE;
1099         OpenMsgBannerInfo *banner_info = NULL;
1100
1101         not_opened_headers = TNY_LIST (user_data);
1102
1103         status = tny_account_get_connection_status (account);
1104         if (err || canceled) {
1105                 /* Unregister the already registered headers */
1106                 tny_list_foreach (not_opened_headers, foreach_unregister_headers, 
1107                                   modest_runtime_get_window_mgr ());
1108                 goto clean;
1109         }
1110
1111         /* Get the error message depending on the protocol */
1112         proto_name = tny_account_get_proto (account);
1113         if (proto_name != NULL) {
1114                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1115         } else {
1116                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1117         }
1118         
1119         /* Create the error messages */
1120         if (tny_list_get_length (not_opened_headers) == 1) {
1121                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1122                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1123                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1124                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1125                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1126                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1127                                                      tny_header_get_subject (header));
1128                         g_object_unref (header);
1129                         g_object_unref (iter);
1130                 } else {
1131                         TnyHeader *header;
1132                         TnyFolder *folder;
1133                         TnyIterator *iter;
1134                         TnyFolderType folder_type;
1135
1136                         iter = tny_list_create_iterator (not_opened_headers);
1137                         header = TNY_HEADER (tny_iterator_get_current (iter));
1138                         folder = tny_header_get_folder (header);
1139                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1140                         show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1141                         g_object_unref (folder);
1142                         g_object_unref (header);
1143                         g_object_unref (iter);
1144                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1145                 }
1146         } else {
1147                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1148         }
1149
1150         /* Create the mail operation */
1151         mail_op = 
1152                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1153                                                                modest_ui_actions_get_msgs_full_error_handler,
1154                                                                error_msg, g_free);
1155         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1156                                          mail_op);
1157
1158         if (show_open_draft) {
1159                 banner_info = g_slice_new (OpenMsgBannerInfo);
1160                 banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1161                 banner_info->banner = NULL;
1162                 banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle, banner_info);
1163         }
1164
1165         modest_mail_operation_get_msgs_full (mail_op,
1166                                              not_opened_headers,
1167                                              open_msg_cb,
1168                                              banner_info,
1169                                              NULL);
1170
1171         /* Frees */
1172  clean:
1173         if (mail_op)
1174                 g_object_unref (mail_op);
1175         g_object_unref (not_opened_headers);
1176         g_object_unref (account);
1177 }
1178
1179 /*
1180  * This function is used by both modest_ui_actions_on_open and
1181  * modest_ui_actions_on_header_activated. This way we always do the
1182  * same when trying to open messages.
1183  */
1184 static void
1185 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1186 {
1187         ModestWindowMgr *mgr = NULL;
1188         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1189         TnyList *not_opened_headers = NULL;
1190         TnyHeaderFlags flags = 0;
1191         TnyAccount *account;
1192         gint uncached_msgs = 0;
1193                 
1194         g_return_if_fail (headers != NULL);
1195
1196         /* Check that only one message is selected for opening */
1197         if (tny_list_get_length (headers) != 1) {
1198                 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1199                                                     NULL, _("mcen_ib_select_one_message"));
1200                 return;
1201         }
1202
1203         mgr = modest_runtime_get_window_mgr ();
1204         iter = tny_list_create_iterator (headers);
1205
1206         /* Get the account */
1207         account = get_account_from_header_list (headers);
1208
1209         if (!account)
1210                 return;
1211
1212         /* Look if we already have a message view for each header. If
1213            true, then remove the header from the list of headers to
1214            open */
1215         not_opened_headers = tny_simple_list_new ();
1216         while (!tny_iterator_is_done (iter)) {
1217
1218                 ModestWindow *window = NULL;
1219                 TnyHeader *header = NULL;
1220                 gboolean found = FALSE;
1221                 
1222                 header = TNY_HEADER (tny_iterator_get_current (iter));
1223                 if (header)
1224                         flags = tny_header_get_flags (header);
1225
1226                 window = NULL;
1227                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1228                 
1229                 /* Do not open again the message and present the
1230                    window to the user */
1231                 if (found) {
1232                         if (window)
1233                                 gtk_window_present (GTK_WINDOW (window));
1234                         else
1235                                 /* the header has been registered already, we don't do
1236                                  * anything but wait for the window to come up*/
1237                                 g_debug ("header %p already registered, waiting for window", header);
1238                 } else {
1239                         tny_list_append (not_opened_headers, G_OBJECT (header));
1240                 }
1241
1242                 if (header)
1243                         g_object_unref (header);
1244
1245                 tny_iterator_next (iter);
1246         }
1247         g_object_unref (iter);
1248         iter = NULL;
1249
1250         /* Open each message */
1251         if (tny_list_get_length (not_opened_headers) == 0)
1252                 goto cleanup;
1253         
1254         /* If some messages would have to be downloaded, ask the user to 
1255          * make a connection. It's generally easier to do this here (in the mainloop) 
1256          * than later in a thread:
1257          */
1258         if (tny_list_get_length (not_opened_headers) > 0) {
1259                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1260
1261                 if (uncached_msgs > 0) {
1262                         /* Allways download if we are online. */
1263                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1264                                 gint response;
1265
1266                                 /* If ask for user permission to download the messages */
1267                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1268                                                                                     ngettext("mcen_nc_get_msg",
1269                                                                                              "mcen_nc_get_msgs",
1270                                                                                              uncached_msgs));
1271
1272                                 /* End if the user does not want to continue */
1273                                 if (response == GTK_RESPONSE_CANCEL)
1274                                         goto cleanup;
1275                         }
1276                 }
1277         }
1278         
1279         /* Register the headers before actually creating the windows: */
1280         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1281         while (!tny_iterator_is_done (iter_not_opened)) {
1282                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1283                 if (header) {
1284                         modest_window_mgr_register_header (mgr, header, NULL);
1285                         g_object_unref (header);
1286                 }
1287                 tny_iterator_next (iter_not_opened);
1288         }
1289         g_object_unref (iter_not_opened);
1290         iter_not_opened = NULL;
1291
1292         /* Connect to the account and perform */
1293         if (uncached_msgs > 0) {
1294                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account), 
1295                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1296         } else {
1297                 /* Call directly the performer, do not need to connect */
1298                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1299                                      g_object_ref (not_opened_headers));
1300         }
1301 cleanup:
1302         /* Clean */
1303         if (account)
1304                 g_object_unref (account);
1305         if (not_opened_headers)
1306                 g_object_unref (not_opened_headers);
1307 }
1308
1309 void
1310 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1311 {
1312         TnyList *headers;
1313
1314         /* Get headers */
1315         headers = get_selected_headers (win);
1316         if (!headers)
1317                 return;
1318
1319         /* Open them */
1320         open_msgs_from_headers (headers, win);
1321
1322         g_object_unref(headers);
1323 }
1324
1325
1326 static void
1327 free_reply_forward_helper (gpointer data)
1328 {
1329         ReplyForwardHelper *helper;
1330
1331         helper = (ReplyForwardHelper *) data;
1332         g_free (helper->account_name);
1333         g_slice_free (ReplyForwardHelper, helper);
1334 }
1335
1336 static void
1337 reply_forward_cb (ModestMailOperation *mail_op,  
1338                   TnyHeader *header, 
1339                   gboolean canceled,
1340                   TnyMsg *msg,
1341                   GError *err,
1342                   gpointer user_data)
1343 {
1344         TnyMsg *new_msg;
1345         ReplyForwardHelper *rf_helper;
1346         ModestWindow *msg_win = NULL;
1347         ModestEditType edit_type;
1348         gchar *from = NULL;
1349         TnyAccount *account = NULL;
1350         ModestWindowMgr *mgr = NULL;
1351         gchar *signature = NULL;
1352         gboolean use_signature;
1353
1354         /* If there was any error. The mail operation could be NULL,
1355            this means that we already have the message downloaded and
1356            that we didn't do a mail operation to retrieve it */
1357         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1358                 return;
1359                         
1360         g_return_if_fail (user_data != NULL);
1361         rf_helper = (ReplyForwardHelper *) user_data;
1362
1363         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1364                                                    rf_helper->account_name);
1365         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1366                                                       rf_helper->account_name, 
1367                                                       &use_signature);
1368
1369         /* Create reply mail */
1370         switch (rf_helper->action) {
1371         case ACTION_REPLY:
1372                 new_msg = 
1373                         modest_tny_msg_create_reply_msg (msg, header, from, 
1374                                                          (use_signature) ? signature : NULL,
1375                                                          rf_helper->reply_forward_type,
1376                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1377                 break;
1378         case ACTION_REPLY_TO_ALL:
1379                 new_msg = 
1380                         modest_tny_msg_create_reply_msg (msg, header, from, 
1381                                                          (use_signature) ? signature : NULL, 
1382                                                          rf_helper->reply_forward_type,
1383                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1384                 edit_type = MODEST_EDIT_TYPE_REPLY;
1385                 break;
1386         case ACTION_FORWARD:
1387                 new_msg = 
1388                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL, 
1389                                                            rf_helper->reply_forward_type);
1390                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1391                 break;
1392         default:
1393                 g_return_if_reached ();
1394                 return;
1395         }
1396
1397         g_free (signature);
1398
1399         if (!new_msg) {
1400                 g_printerr ("modest: failed to create message\n");
1401                 goto cleanup;
1402         }
1403
1404         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1405                                                                        rf_helper->account_name,
1406                                                                        TNY_ACCOUNT_TYPE_STORE);
1407         if (!account) {
1408                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1409                 goto cleanup;
1410         }
1411
1412         /* Create and register the windows */
1413         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1414         mgr = modest_runtime_get_window_mgr ();
1415         modest_window_mgr_register_window (mgr, msg_win);
1416
1417         if (rf_helper->parent_window != NULL) {
1418                 gdouble parent_zoom;
1419
1420                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1421                 modest_window_set_zoom (msg_win, parent_zoom);
1422         }
1423
1424         /* Show edit window */
1425         gtk_widget_show_all (GTK_WIDGET (msg_win));
1426
1427 cleanup:
1428         if (msg_win)
1429                 g_object_unref (msg_win);
1430         if (new_msg)
1431                 g_object_unref (G_OBJECT (new_msg));
1432         if (account)
1433                 g_object_unref (G_OBJECT (account));
1434 /*      g_object_unref (msg); */
1435         free_reply_forward_helper (rf_helper);
1436 }
1437
1438 /* Checks a list of headers. If any of them are not currently
1439  * downloaded (CACHED) then returns TRUE else returns FALSE.
1440  */
1441 static gint
1442 header_list_count_uncached_msgs (TnyList *header_list)
1443 {
1444         TnyIterator *iter;
1445         gint uncached_messages = 0;
1446
1447         iter = tny_list_create_iterator (header_list);
1448         while (!tny_iterator_is_done (iter)) {
1449                 TnyHeader *header;
1450
1451                 header = TNY_HEADER (tny_iterator_get_current (iter));
1452                 if (header) {
1453                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1454                                 uncached_messages ++;
1455                         g_object_unref (header);
1456                 }
1457
1458                 tny_iterator_next (iter);
1459         }
1460         g_object_unref (iter);
1461
1462         return uncached_messages;
1463 }
1464
1465 /* Returns FALSE if the user does not want to download the
1466  * messages. Returns TRUE if the user allowed the download.
1467  */
1468 static gboolean
1469 connect_to_get_msg (ModestWindow *win,
1470                     gint num_of_uncached_msgs,
1471                     TnyAccount *account)
1472 {
1473         GtkResponseType response;
1474
1475         /* Allways download if we are online. */
1476         if (tny_device_is_online (modest_runtime_get_device ()))
1477                 return TRUE;
1478
1479         /* If offline, then ask for user permission to download the messages */
1480         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1481                         ngettext("mcen_nc_get_msg",
1482                         "mcen_nc_get_msgs",
1483                         num_of_uncached_msgs));
1484
1485         if (response == GTK_RESPONSE_CANCEL)
1486                 return FALSE;
1487
1488         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1489 }
1490
1491 /*
1492  * Common code for the reply and forward actions
1493  */
1494 static void
1495 reply_forward (ReplyForwardAction action, ModestWindow *win)
1496 {
1497         ModestMailOperation *mail_op = NULL;
1498         TnyList *header_list = NULL;
1499         ReplyForwardHelper *rf_helper = NULL;
1500         guint reply_forward_type;
1501         gboolean continue_download = TRUE;
1502         gboolean do_retrieve = TRUE;
1503         
1504         g_return_if_fail (MODEST_IS_WINDOW(win));
1505
1506         /* we need an account when editing */
1507         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1508                 if (!modest_ui_actions_run_account_setup_wizard (win))
1509                         return;
1510         }
1511         
1512         header_list = get_selected_headers (win);
1513         if (!header_list)
1514                 return;
1515
1516         reply_forward_type = 
1517                 modest_conf_get_int (modest_runtime_get_conf (),
1518                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1519                                      NULL);
1520
1521         /* check if we need to download msg before asking about it */
1522         do_retrieve = (action == ACTION_FORWARD) ||
1523                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1524
1525         if (do_retrieve){
1526                 gint num_of_unc_msgs;
1527
1528                 /* check that the messages have been previously downloaded */
1529                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1530                 /* If there are any uncached message ask the user
1531                  * whether he/she wants to download them. */
1532                 if (num_of_unc_msgs) {
1533                         TnyAccount *account = get_account_from_header_list (header_list);
1534                         if (account) {
1535                                 continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1536                                 g_object_unref (account);
1537                         }
1538                 }
1539         }
1540
1541         if (!continue_download) {
1542                 g_object_unref (header_list);
1543                 return;
1544         }
1545         
1546         /* We assume that we can only select messages of the
1547            same folder and that we reply all of them from the
1548            same account. In fact the interface currently only
1549            allows single selection */
1550         
1551         /* Fill helpers */
1552         rf_helper = g_slice_new0 (ReplyForwardHelper);
1553         rf_helper->reply_forward_type = reply_forward_type;
1554         rf_helper->action = action;
1555         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1556         
1557         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1558                 rf_helper->parent_window = GTK_WIDGET (win);
1559         if (!rf_helper->account_name)
1560                 rf_helper->account_name =
1561                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1562
1563         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1564                 TnyMsg *msg;
1565                 TnyHeader *header;
1566                 /* Get header and message. Do not free them here, the
1567                    reply_forward_cb must do it */
1568                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1569                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1570                 if (!msg || !header) {
1571                         if (msg)
1572                                 g_object_unref (msg);
1573                         g_printerr ("modest: no message found\n");
1574                         return;
1575                 } else {
1576                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1577                 }
1578                 if (header)
1579                         g_object_unref (header);
1580         } else {
1581                 TnyHeader *header;
1582                 TnyIterator *iter;
1583
1584                 /* Only reply/forward to one message */
1585                 iter = tny_list_create_iterator (header_list);
1586                 header = TNY_HEADER (tny_iterator_get_current (iter));
1587                 g_object_unref (iter);
1588
1589                 if (header) {
1590                         /* Retrieve messages */
1591                         if (do_retrieve) {
1592                                 mail_op = 
1593                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1594                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1595                                                                                        NULL, NULL);
1596                                 modest_mail_operation_queue_add (
1597                                         modest_runtime_get_mail_operation_queue (), mail_op);
1598                                 
1599                                 modest_mail_operation_get_msg (mail_op,
1600                                                                header,
1601                                                                reply_forward_cb,
1602                                                                rf_helper);
1603                                 /* Clean */
1604                                 g_object_unref(mail_op);
1605                         } else {
1606                                 /* we put a ref here to prevent double unref as the reply
1607                                  * forward callback unrefs the header at its end */
1608                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1609                         }
1610
1611
1612                         g_object_unref (header);
1613                 }
1614
1615         }
1616
1617         /* Free */
1618         g_object_unref (header_list);
1619 }
1620
1621 void
1622 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1623 {
1624         g_return_if_fail (MODEST_IS_WINDOW(win));
1625
1626         reply_forward (ACTION_REPLY, win);
1627 }
1628
1629 void
1630 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1631 {
1632         g_return_if_fail (MODEST_IS_WINDOW(win));
1633
1634         reply_forward (ACTION_FORWARD, win);
1635 }
1636
1637 void
1638 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1639 {
1640         g_return_if_fail (MODEST_IS_WINDOW(win));
1641
1642         reply_forward (ACTION_REPLY_TO_ALL, win);
1643 }
1644
1645 void 
1646 modest_ui_actions_on_next (GtkAction *action, 
1647                            ModestWindow *window)
1648 {
1649         if (MODEST_IS_MAIN_WINDOW (window)) {
1650                 GtkWidget *header_view;
1651
1652                 header_view = modest_main_window_get_child_widget (
1653                                 MODEST_MAIN_WINDOW(window),
1654                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1655                 if (!header_view)
1656                         return;
1657         
1658                 modest_header_view_select_next (
1659                                 MODEST_HEADER_VIEW(header_view)); 
1660         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1661                 modest_msg_view_window_select_next_message (
1662                                 MODEST_MSG_VIEW_WINDOW (window));
1663         } else {
1664                 g_return_if_reached ();
1665         }
1666 }
1667
1668 void 
1669 modest_ui_actions_on_prev (GtkAction *action, 
1670                            ModestWindow *window)
1671 {
1672         g_return_if_fail (MODEST_IS_WINDOW(window));
1673
1674         if (MODEST_IS_MAIN_WINDOW (window)) {
1675                 GtkWidget *header_view;
1676                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1677                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1678                 if (!header_view)
1679                         return;
1680                 
1681                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1682         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1683                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1684         } else {
1685                 g_return_if_reached ();
1686         }
1687 }
1688
1689 void 
1690 modest_ui_actions_on_sort (GtkAction *action, 
1691                            ModestWindow *window)
1692 {
1693         g_return_if_fail (MODEST_IS_WINDOW(window));
1694
1695         if (MODEST_IS_MAIN_WINDOW (window)) {
1696                 GtkWidget *header_view;
1697                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1698                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1699                 if (!header_view) {
1700                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1701
1702                         return;
1703                 }
1704
1705                 /* Show sorting dialog */
1706                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1707         }
1708 }
1709
1710 static void
1711 new_messages_arrived (ModestMailOperation *self, 
1712                       TnyList *new_headers,
1713                       gpointer user_data)
1714 {
1715         GObject *source;
1716         gboolean show_visual_notifications;
1717
1718         source = modest_mail_operation_get_source (self);
1719         show_visual_notifications = (source) ? FALSE : TRUE;
1720         if (source)
1721                 g_object_unref (source);
1722
1723         /* Notify new messages have been downloaded. If the
1724            send&receive was invoked by the user then do not show any
1725            visual notification, only play a sound and activate the LED
1726            (for the Maemo version) */
1727         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1728                 modest_platform_on_new_headers_received (new_headers, 
1729                                                          show_visual_notifications);
1730
1731 }
1732
1733 gboolean
1734 retrieve_all_messages_cb (GObject *source,
1735                           guint num_msgs,
1736                           guint retrieve_limit)
1737 {
1738         GtkWindow *window;
1739         gchar *msg;
1740         gint response;
1741
1742         window = GTK_WINDOW (source);
1743         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1744                                num_msgs, retrieve_limit);
1745
1746         /* Ask the user if they want to retrieve all the messages */
1747         response = 
1748                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1749                                                                       _("mcen_bd_get_all"),
1750                                                                       _("mcen_bd_newest_only"));
1751         /* Free and return */
1752         g_free (msg);
1753         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1754 }
1755
1756 typedef struct {
1757         TnyAccount *account;
1758         ModestWindow *win;
1759         gchar *account_name;
1760         gboolean poke_status;
1761 } SendReceiveInfo;
1762
1763 static void
1764 do_send_receive_performer (gboolean canceled, 
1765                            GError *err,
1766                            GtkWindow *parent_window, 
1767                            TnyAccount *account, 
1768                            gpointer user_data)
1769 {
1770         ModestMailOperation *mail_op;
1771         SendReceiveInfo *info;
1772
1773         info = (SendReceiveInfo *) user_data;
1774
1775         if (err || canceled) {
1776                 goto clean;
1777         }
1778
1779         /* Set send/receive operation in progress */    
1780         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1781                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1782         }
1783         
1784         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1785                                                                  modest_ui_actions_send_receive_error_handler,
1786                                                                  NULL, NULL);
1787
1788         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1789                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1790                                   G_CALLBACK (on_send_receive_finished), 
1791                                   info->win);
1792
1793         /* Send & receive. */
1794         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1795         modest_mail_operation_update_account (mail_op, info->account_name, info->poke_status,
1796                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1797                                               new_messages_arrived, info->win);
1798         g_object_unref (G_OBJECT (mail_op));
1799         
1800  clean:
1801         /* Frees */
1802         if (info->account_name)
1803                 g_free (info->account_name);
1804         if (info->win)
1805                 g_object_unref (info->win);
1806         if (info->account)
1807                 g_object_unref (info->account);
1808         g_slice_free (SendReceiveInfo, info);
1809 }
1810
1811 /*
1812  * This function performs the send & receive required actions. The
1813  * window is used to create the mail operation. Typically it should
1814  * always be the main window, but we pass it as argument in order to
1815  * be more flexible.
1816  */
1817 void
1818 modest_ui_actions_do_send_receive (const gchar *account_name, 
1819                                    gboolean force_connection,
1820                                    gboolean poke_status,
1821                                    ModestWindow *win)
1822 {
1823         gchar *acc_name = NULL;
1824         SendReceiveInfo *info;
1825         ModestTnyAccountStore *acc_store;
1826
1827         /* If no account name was provided then get the current account, and if
1828            there is no current account then pick the default one: */
1829         if (!account_name) {
1830                 if (win)
1831                         acc_name = g_strdup (modest_window_get_active_account (win));
1832                 if (!acc_name)
1833                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1834                 if (!acc_name) {
1835                         g_printerr ("modest: cannot get default account\n");
1836                         return;
1837                 }
1838         } else {
1839                 acc_name = g_strdup (account_name);
1840         }
1841
1842         acc_store = modest_runtime_get_account_store ();
1843
1844         /* Create the info for the connect and perform */
1845         info = g_slice_new (SendReceiveInfo);
1846         info->account_name = acc_name;
1847         info->win = (win) ? g_object_ref (win) : NULL;
1848         info->poke_status = poke_status;
1849         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1850                                                                      TNY_ACCOUNT_TYPE_STORE);
1851
1852         /* Invoke the connect and perform */
1853         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
1854                                              force_connection, info->account, 
1855                                              do_send_receive_performer, info);
1856 }
1857
1858
1859 static void
1860 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1861                                   ModestWindow *win)
1862 {
1863         TnyTransportAccount *transport_account;
1864         TnySendQueue *send_queue = NULL;
1865         GError *error = NULL;
1866
1867         /* Get transport account */
1868         transport_account =
1869                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1870                                       (modest_runtime_get_account_store(),
1871                                        account_name,
1872                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1873         if (!transport_account) {
1874                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1875                 goto frees;
1876         }
1877
1878         /* Get send queue*/
1879         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1880         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1881                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1882                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1883                              "modest: could not find send queue for account\n");
1884         } else {
1885                 /* Cancel the current send */
1886                 tny_account_cancel (TNY_ACCOUNT (transport_account));
1887
1888                 /* Suspend all pending messages */
1889                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
1890         }
1891
1892  frees:
1893         if (transport_account != NULL) 
1894                 g_object_unref (G_OBJECT (transport_account));
1895 }
1896
1897 static void
1898 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1899 {
1900         GSList *account_names, *iter;
1901
1902         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1903                                                           TRUE);
1904
1905         iter = account_names;
1906         while (iter) {                  
1907                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1908                 iter = g_slist_next (iter);
1909         }
1910
1911         modest_account_mgr_free_account_names (account_names);
1912         account_names = NULL;
1913 }
1914
1915 void
1916 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1917
1918 {
1919         /* Check if accounts exist */
1920         gboolean accounts_exist = 
1921                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1922         
1923         /* If not, allow the user to create an account before trying to send/receive. */
1924         if (!accounts_exist)
1925                 modest_ui_actions_on_accounts (NULL, win);
1926         
1927         /* Cancel all sending operaitons */     
1928         modest_ui_actions_cancel_send_all (win);
1929 }
1930
1931 /*
1932  * Refreshes all accounts. This function will be used by automatic
1933  * updates
1934  */
1935 void
1936 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
1937                                        gboolean force_connection,
1938                                        gboolean poke_status)
1939 {
1940         GSList *account_names, *iter;
1941
1942         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1943                                                           TRUE);
1944
1945         iter = account_names;
1946         while (iter) {                  
1947                 modest_ui_actions_do_send_receive ((const char*) iter->data, 
1948                                                    force_connection, 
1949                                                    poke_status, win);
1950                 iter = g_slist_next (iter);
1951         }
1952
1953         modest_account_mgr_free_account_names (account_names);
1954         account_names = NULL;
1955 }
1956
1957 /*
1958  * Handler of the click on Send&Receive button in the main toolbar
1959  */
1960 void
1961 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1962 {
1963         /* Check if accounts exist */
1964         gboolean accounts_exist;
1965
1966         accounts_exist =
1967                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1968         
1969         /* If not, allow the user to create an account before trying to send/receive. */
1970         if (!accounts_exist)
1971                 modest_ui_actions_on_accounts (NULL, win);
1972         
1973         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1974         if (MODEST_IS_MAIN_WINDOW (win)) {
1975                 GtkWidget *folder_view;
1976                 TnyFolderStore *folder_store;
1977
1978                 folder_view = 
1979                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1980                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1981                 if (!folder_view)
1982                         return;
1983                 
1984                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1985         
1986                 if (folder_store)
1987                         g_object_unref (folder_store);
1988         }       
1989         
1990         /* Refresh the active account. Force the connection if needed
1991            and poke the status of all folders */
1992         modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, win);
1993 }
1994
1995
1996 void
1997 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1998 {
1999         ModestConf *conf;
2000         GtkWidget *header_view;
2001         
2002         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2003
2004         header_view = modest_main_window_get_child_widget (main_window,
2005                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2006         if (!header_view)
2007                 return;
2008
2009         conf = modest_runtime_get_conf ();
2010         
2011         /* what is saved/restored is depending on the style; thus; we save with
2012          * old style, then update the style, and restore for this new style
2013          */
2014         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2015         
2016         if (modest_header_view_get_style
2017             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2018                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2019                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2020         else
2021                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2022                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2023
2024         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2025                                       MODEST_CONF_HEADER_VIEW_KEY);
2026 }
2027
2028
2029 void 
2030 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
2031                                       TnyHeader *header,
2032                                       ModestMainWindow *main_window)
2033 {
2034         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2035         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2036         
2037         /* in the case the folder is empty, show the empty folder message and focus
2038          * folder view */
2039         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2040                 if (modest_header_view_is_empty (header_view)) {
2041                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2042                         GtkWidget *folder_view = 
2043                                 modest_main_window_get_child_widget (main_window,
2044                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2045                         if (folder != NULL) 
2046                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2047                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2048                         return;
2049                 }
2050         }
2051         /* If no header has been selected then exit */
2052         if (!header)
2053                 return;
2054
2055         /* Update focus */
2056         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2057             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2058
2059         /* Update toolbar dimming state */
2060         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2061         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2062 }
2063
2064 void
2065 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2066                                        TnyHeader *header,
2067                                        ModestMainWindow *main_window)
2068 {
2069         TnyList *headers;
2070
2071         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2072
2073         if (!header)
2074                 return;
2075
2076         if (modest_header_view_count_selected_headers (header_view) > 1) {
2077                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2078                 return;
2079         }
2080
2081
2082 /*      headers = tny_simple_list_new (); */
2083 /*      tny_list_prepend (headers, G_OBJECT (header)); */
2084         headers = modest_header_view_get_selected_headers (header_view);
2085
2086         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2087
2088         g_object_unref (headers);
2089 }
2090
2091 static void
2092 set_active_account_from_tny_account (TnyAccount *account,
2093                                      ModestWindow *window)
2094 {
2095         const gchar *server_acc_name = tny_account_get_id (account);
2096         
2097         /* We need the TnyAccount provided by the
2098            account store because that is the one that
2099            knows the name of the Modest account */
2100         TnyAccount *modest_server_account = modest_server_account = 
2101                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2102                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2103                                                              server_acc_name);
2104         if (!modest_server_account) {
2105                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2106                 return;
2107         }
2108
2109         /* Update active account, but only if it's not a pseudo-account */
2110         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2111             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2112                 const gchar *modest_acc_name = 
2113                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2114                 if (modest_acc_name)
2115                         modest_window_set_active_account (window, modest_acc_name);
2116         }
2117         
2118         g_object_unref (modest_server_account);
2119 }
2120
2121
2122 static void
2123 folder_refreshed_cb (ModestMailOperation *mail_op, 
2124                      TnyFolder *folder, 
2125                      gpointer user_data)
2126 {
2127         ModestMainWindow *win = NULL;
2128         GtkWidget *header_view;
2129
2130         g_return_if_fail (TNY_IS_FOLDER (folder));
2131
2132         win = MODEST_MAIN_WINDOW (user_data);
2133         header_view = 
2134                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2135
2136         if (header_view) {
2137                 TnyFolder *current_folder;
2138
2139                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2140                 if (current_folder != NULL && folder != current_folder) {
2141                         g_object_unref (current_folder);
2142                         return;
2143                 } else if (current_folder)
2144                         g_object_unref (current_folder);
2145         }
2146
2147         /* Check if folder is empty and set headers view contents style */
2148         if (tny_folder_get_all_count (folder) == 0)
2149                 modest_main_window_set_contents_style (win,
2150                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2151 }
2152
2153 void 
2154 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2155                                                TnyFolderStore *folder_store, 
2156                                                gboolean selected,
2157                                                ModestMainWindow *main_window)
2158 {
2159         ModestConf *conf;
2160         GtkWidget *header_view;
2161
2162         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2163
2164         header_view = modest_main_window_get_child_widget(main_window,
2165                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2166         if (!header_view)
2167                 return;
2168         
2169         conf = modest_runtime_get_conf ();
2170
2171         if (TNY_IS_ACCOUNT (folder_store)) {
2172                 if (selected) {
2173                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2174                         
2175                         /* Show account details */
2176                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2177                 }
2178         } else {
2179                 if (TNY_IS_FOLDER (folder_store) && selected) {
2180                         
2181                         /* Update the active account */
2182                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2183                         if (account) {
2184                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2185                                 g_object_unref (account);
2186                                 account = NULL;
2187                         }
2188
2189                         /* Set the header style by default, it could
2190                            be changed later by the refresh callback to
2191                            empty */
2192                         modest_main_window_set_contents_style (main_window, 
2193                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2194
2195                         /* Set folder on header view. This function
2196                            will call tny_folder_refresh_async so we
2197                            pass a callback that will be called when
2198                            finished. We use that callback to set the
2199                            empty view if there are no messages */
2200                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2201                                                        TNY_FOLDER (folder_store),
2202                                                        folder_refreshed_cb,
2203                                                        main_window);
2204                         
2205                         /* Restore configuration. We need to do this
2206                            *after* the set_folder because the widget
2207                            memory asks the header view about its
2208                            folder  */
2209                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2210                                                       G_OBJECT(header_view),
2211                                                       MODEST_CONF_HEADER_VIEW_KEY);
2212                 } else {
2213                         /* Update the active account */
2214                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2215                         /* Save only if we're seeing headers */
2216                         if (modest_main_window_get_contents_style (main_window) ==
2217                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2218                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2219                                                            MODEST_CONF_HEADER_VIEW_KEY);
2220                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2221                 }
2222         }
2223
2224         /* Update toolbar dimming state */
2225         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2226 }
2227
2228 void 
2229 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2230                                      ModestWindow *win)
2231 {
2232         GtkWidget *dialog;
2233         gchar *txt, *item;
2234         gboolean online;
2235
2236         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2237         
2238         online = tny_device_is_online (modest_runtime_get_device());
2239
2240         if (online) {
2241                 /* already online -- the item is simply not there... */
2242                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2243                                                  GTK_DIALOG_MODAL,
2244                                                  GTK_MESSAGE_WARNING,
2245                                                  GTK_BUTTONS_NONE,
2246                                                  _("The %s you selected cannot be found"),
2247                                                  item);
2248                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2249                 gtk_dialog_run (GTK_DIALOG(dialog));
2250         } else {
2251                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2252                                                       GTK_WINDOW (win),
2253                                                       GTK_DIALOG_MODAL,
2254                                                       _("mcen_bd_dialog_cancel"),
2255                                                       GTK_RESPONSE_REJECT,
2256                                                       _("mcen_bd_dialog_ok"),
2257                                                       GTK_RESPONSE_ACCEPT,
2258                                                       NULL);
2259                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2260                                          "Do you want to get online?"), item);
2261                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2262                                     gtk_label_new (txt), FALSE, FALSE, 0);
2263                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2264                 g_free (txt);
2265
2266                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2267                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2268                         /* TODO: Comment about why is this commented out: */
2269                         /* modest_platform_connect_and_wait (); */
2270                 }
2271         }
2272         gtk_widget_destroy (dialog);
2273 }
2274
2275 void
2276 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2277                                      ModestWindow *win)
2278 {
2279         /* g_message ("%s %s", __FUNCTION__, link); */
2280 }       
2281
2282
2283 void
2284 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2285                                         ModestWindow *win)
2286 {
2287         modest_platform_activate_uri (link);
2288 }
2289
2290 void
2291 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2292                                           ModestWindow *win)
2293 {
2294         modest_platform_show_uri_popup (link);
2295 }
2296
2297 void
2298 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2299                                              ModestWindow *win)
2300 {
2301         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2302 }
2303
2304 void
2305 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2306                                           const gchar *address,
2307                                           ModestWindow *win)
2308 {
2309         /* g_message ("%s %s", __FUNCTION__, address); */
2310 }
2311
2312 static void
2313 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2314                       TnyMsg *saved_draft,
2315                       gpointer user_data)
2316 {
2317         ModestMsgEditWindow *edit_window;
2318         ModestMainWindow *win;
2319
2320         /* FIXME. Make the header view sensitive again. This is a
2321          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2322          * for details */
2323         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2324                                          modest_runtime_get_window_mgr(), FALSE));
2325         if (win != NULL) {
2326                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2327                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2328                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2329         }
2330
2331         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2332
2333         /* It might not be a good idea to do nothing if there was an error,
2334          * so let's at least show a generic error banner. */
2335         /* TODO error while saving attachment, show "Saving draft failed" banner */
2336         if (modest_mail_operation_get_error (mail_op) != NULL) {
2337                 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_op))->message);
2338                 modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
2339         } else {
2340                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2341         }
2342         g_object_unref(edit_window);
2343 }
2344
2345 gboolean
2346 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2347 {
2348         TnyTransportAccount *transport_account;
2349         ModestMailOperation *mail_operation;
2350         MsgData *data;
2351         gchar *account_name, *from;
2352         ModestAccountMgr *account_mgr;
2353 /*      char *info_text; */
2354         gboolean had_error = FALSE;
2355         guint64 available_disk, expected_size;
2356         gint parts_count;
2357         guint64 parts_size;
2358         ModestMainWindow *win;
2359
2360         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2361         
2362         data = modest_msg_edit_window_get_msg_data (edit_window);
2363
2364         /* Check size */
2365         available_disk = modest_folder_available_space (NULL);
2366         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2367         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2368                                                  data->html_body,
2369                                                  parts_count,
2370                                                  parts_size);
2371
2372         if ((available_disk != -1) && expected_size > available_disk) {
2373                 modest_msg_edit_window_free_msg_data (edit_window, data);
2374
2375                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2376                 return FALSE;
2377         }
2378
2379         account_name = g_strdup (data->account_name);
2380         account_mgr = modest_runtime_get_account_mgr();
2381         if (!account_name)
2382                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2383         if (!account_name) 
2384                 account_name = modest_account_mgr_get_default_account (account_mgr);
2385         if (!account_name) {
2386                 g_printerr ("modest: no account found\n");
2387                 modest_msg_edit_window_free_msg_data (edit_window, data);
2388                 return FALSE;
2389         }
2390
2391         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2392                 account_name = g_strdup (data->account_name);
2393         }
2394
2395         transport_account =
2396                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2397                                       (modest_runtime_get_account_store(),
2398                                        account_name,
2399                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2400         if (!transport_account) {
2401                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2402                 g_free (account_name);
2403                 modest_msg_edit_window_free_msg_data (edit_window, data);
2404                 return FALSE;
2405         }
2406         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2407
2408         /* Create the mail operation */         
2409         mail_operation = modest_mail_operation_new (NULL);
2410         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2411
2412         modest_mail_operation_save_to_drafts (mail_operation,
2413                                               transport_account,
2414                                               data->draft_msg,
2415                                               from,
2416                                               data->to, 
2417                                               data->cc, 
2418                                               data->bcc,
2419                                               data->subject, 
2420                                               data->plain_body, 
2421                                               data->html_body,
2422                                               data->attachments,
2423                                               data->images,
2424                                               data->priority_flags,
2425                                               on_save_to_drafts_cb,
2426                                               g_object_ref(edit_window));
2427
2428         /* Use the main window as the parent of the banner, if the
2429            main window does not exist it won't be shown, if the parent
2430            window exists then it's properly shown. We don't use the
2431            editor window because it could be closed (save to drafts
2432            could happen after closing the window */
2433         win = (ModestMainWindow *)
2434                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2435         if (win) {
2436                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2437                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2438                 g_free (text);
2439         }
2440         modest_msg_edit_window_set_modified (edit_window, FALSE);
2441
2442         /* Frees */
2443         g_free (from);
2444         g_free (account_name);
2445         g_object_unref (G_OBJECT (transport_account));
2446         g_object_unref (G_OBJECT (mail_operation));
2447
2448         modest_msg_edit_window_free_msg_data (edit_window, data);
2449
2450         /* ** FIXME **
2451          * If the drafts folder is selected then make the header view
2452          * insensitive while the message is being saved to drafts
2453          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2454          * is not very clean but it avoids letting the drafts folder
2455          * in an inconsistent state: the user could edit the message
2456          * being saved and undesirable things would happen.
2457          * In the average case the user won't notice anything at
2458          * all. In the worst case (the user is editing a really big
2459          * file from Drafts) the header view will be insensitive
2460          * during the saving process (10 or 20 seconds, depending on
2461          * the message). Anyway this is just a quick workaround: once
2462          * we find a better solution it should be removed
2463          * See NB#65125 (commend #18) for details.
2464          */
2465         if (!had_error && win != NULL) {
2466                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2467                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2468                 if (view != NULL) {
2469                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2470                         if (folder) {
2471                                 if (modest_tny_folder_is_local_folder(folder)) {
2472                                         TnyFolderType folder_type;
2473                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2474                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2475                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2476                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2477                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2478                                         }
2479                                 }
2480                         }
2481                         if (folder != NULL) g_object_unref(folder);
2482                 }
2483         }
2484
2485         return !had_error;
2486 }
2487
2488 /* For instance, when clicking the Send toolbar button when editing a message: */
2489 gboolean
2490 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2491 {
2492         TnyTransportAccount *transport_account = NULL;
2493         gboolean had_error = FALSE;
2494         guint64 available_disk, expected_size;
2495         gint parts_count;
2496         guint64 parts_size;
2497
2498         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2499
2500         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2501                 return TRUE;
2502         
2503         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2504
2505         /* Check size */
2506         available_disk = modest_folder_available_space (NULL);
2507         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2508         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2509                                                  data->html_body,
2510                                                  parts_count,
2511                                                  parts_size);
2512
2513         if ((available_disk != -1) && expected_size > available_disk) {
2514                 modest_msg_edit_window_free_msg_data (edit_window, data);
2515
2516                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2517                 return FALSE;
2518         }
2519
2520         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2521         gchar *account_name = g_strdup (data->account_name);
2522         if (!account_name)
2523                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2524
2525         if (!account_name) 
2526                 account_name = modest_account_mgr_get_default_account (account_mgr);
2527                 
2528         if (!account_name) {
2529                 modest_msg_edit_window_free_msg_data (edit_window, data);
2530                 /* Run account setup wizard */
2531                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2532                         return TRUE;
2533                 }
2534         }
2535         
2536         /* Get the currently-active transport account for this modest account: */
2537         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2538                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2539                                                           (modest_runtime_get_account_store(),
2540                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2541         }
2542         
2543         if (!transport_account) {
2544                 modest_msg_edit_window_free_msg_data (edit_window, data);
2545                 /* Run account setup wizard */
2546                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2547                         return TRUE;
2548         }
2549         
2550         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2551
2552         /* Create the mail operation */
2553         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2554         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2555
2556         modest_mail_operation_send_new_mail (mail_operation,
2557                                              transport_account,
2558                                              data->draft_msg,
2559                                              from,
2560                                              data->to, 
2561                                              data->cc, 
2562                                              data->bcc,
2563                                              data->subject, 
2564                                              data->plain_body, 
2565                                              data->html_body,
2566                                              data->attachments,
2567                                              data->images,
2568                                              data->priority_flags);
2569
2570         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2571                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2572
2573
2574         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2575                 const GError *error = modest_mail_operation_get_error (mail_operation);
2576                 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2577                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2578                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2579                         had_error = TRUE;
2580                 }
2581         }
2582                                              
2583         /* Free data: */
2584         g_free (from);
2585         g_free (account_name);
2586         g_object_unref (G_OBJECT (transport_account));
2587         g_object_unref (G_OBJECT (mail_operation));
2588
2589         modest_msg_edit_window_free_msg_data (edit_window, data);
2590
2591         if (!had_error) {
2592                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2593
2594                 /* Save settings and close the window: */
2595                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2596         }
2597
2598         return !had_error;
2599 }
2600
2601 void 
2602 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2603                                   ModestMsgEditWindow *window)
2604 {
2605         ModestMsgEditFormatState *format_state = NULL;
2606
2607         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2608         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2609
2610         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2611                 return;
2612
2613         format_state = modest_msg_edit_window_get_format_state (window);
2614         g_return_if_fail (format_state != NULL);
2615
2616         format_state->bold = gtk_toggle_action_get_active (action);
2617         modest_msg_edit_window_set_format_state (window, format_state);
2618         g_free (format_state);
2619         
2620 }
2621
2622 void 
2623 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2624                                      ModestMsgEditWindow *window)
2625 {
2626         ModestMsgEditFormatState *format_state = NULL;
2627
2628         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2629         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2630
2631         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2632                 return;
2633
2634         format_state = modest_msg_edit_window_get_format_state (window);
2635         g_return_if_fail (format_state != NULL);
2636
2637         format_state->italics = gtk_toggle_action_get_active (action);
2638         modest_msg_edit_window_set_format_state (window, format_state);
2639         g_free (format_state);
2640         
2641 }
2642
2643 void 
2644 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2645                                      ModestMsgEditWindow *window)
2646 {
2647         ModestMsgEditFormatState *format_state = NULL;
2648
2649         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2650         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2651
2652         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2653                 return;
2654
2655         format_state = modest_msg_edit_window_get_format_state (window);
2656         g_return_if_fail (format_state != NULL);
2657
2658         format_state->bullet = gtk_toggle_action_get_active (action);
2659         modest_msg_edit_window_set_format_state (window, format_state);
2660         g_free (format_state);
2661         
2662 }
2663
2664 void 
2665 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2666                                      GtkRadioAction *selected,
2667                                      ModestMsgEditWindow *window)
2668 {
2669         ModestMsgEditFormatState *format_state = NULL;
2670         GtkJustification value;
2671
2672         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2673
2674         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2675                 return;
2676
2677         value = gtk_radio_action_get_current_value (selected);
2678
2679         format_state = modest_msg_edit_window_get_format_state (window);
2680         g_return_if_fail (format_state != NULL);
2681
2682         format_state->justification = value;
2683         modest_msg_edit_window_set_format_state (window, format_state);
2684         g_free (format_state);
2685 }
2686
2687 void 
2688 modest_ui_actions_on_select_editor_color (GtkAction *action,
2689                                           ModestMsgEditWindow *window)
2690 {
2691         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2692         g_return_if_fail (GTK_IS_ACTION (action));
2693
2694         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2695                 return;
2696
2697         modest_msg_edit_window_select_color (window);
2698 }
2699
2700 void 
2701 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2702                                                      ModestMsgEditWindow *window)
2703 {
2704         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2705         g_return_if_fail (GTK_IS_ACTION (action));
2706
2707         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2708                 return;
2709
2710         modest_msg_edit_window_select_background_color (window);
2711 }
2712
2713 void 
2714 modest_ui_actions_on_insert_image (GtkAction *action,
2715                                    ModestMsgEditWindow *window)
2716 {
2717         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2718         g_return_if_fail (GTK_IS_ACTION (action));
2719
2720         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2721                 return;
2722
2723         modest_msg_edit_window_insert_image (window);
2724 }
2725
2726 void 
2727 modest_ui_actions_on_attach_file (GtkAction *action,
2728                                   ModestMsgEditWindow *window)
2729 {
2730         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2731         g_return_if_fail (GTK_IS_ACTION (action));
2732
2733         modest_msg_edit_window_offer_attach_file (window);
2734 }
2735
2736 void 
2737 modest_ui_actions_on_remove_attachments (GtkAction *action,
2738                                          ModestMsgEditWindow *window)
2739 {
2740         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2741         g_return_if_fail (GTK_IS_ACTION (action));
2742
2743         modest_msg_edit_window_remove_attachments (window, NULL);
2744 }
2745
2746 static void
2747 do_create_folder_cb (ModestMailOperation *mail_op,
2748                      TnyFolderStore *parent_folder, 
2749                      TnyFolder *new_folder,
2750                      gpointer user_data)
2751 {
2752         gchar *suggested_name = (gchar *) user_data;
2753         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2754
2755         if (modest_mail_operation_get_error (mail_op)) {
2756                 /* Show an error */
2757                 modest_platform_information_banner (GTK_WIDGET (source_win), NULL,
2758                                                     _("mail_in_ui_folder_create_error"));
2759
2760                 /* Try again */
2761                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2762         } else {
2763                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2764                  * FIXME: any other? */         
2765                 GtkWidget *folder_view;
2766
2767                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2768                         folder_view = 
2769                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2770                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2771                 else
2772                         folder_view =
2773                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2774                 
2775                 /* Select the newly created folder */
2776                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2777                                                   new_folder, FALSE);
2778                 g_object_unref (new_folder);
2779         }
2780         /* Free. Note that the first time it'll be NULL so noop */
2781         g_free (suggested_name);
2782         g_object_unref (source_win);
2783 }
2784
2785 static void
2786 do_create_folder (GtkWindow *parent_window, 
2787                   TnyFolderStore *parent_folder, 
2788                   const gchar *suggested_name)
2789 {
2790         gint result;
2791         gchar *folder_name = NULL;
2792
2793         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2794                                                         parent_folder,
2795                                                         (gchar *) suggested_name,
2796                                                         &folder_name);
2797         
2798         if (result == GTK_RESPONSE_ACCEPT) {
2799                 ModestMailOperation *mail_op;
2800                 
2801                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2802                         
2803                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2804                                                  mail_op);
2805                 modest_mail_operation_create_folder (mail_op,
2806                                                      parent_folder,
2807                                                      (const gchar *) folder_name,
2808                                                      do_create_folder_cb,
2809                                                      folder_name);
2810                 g_object_unref (mail_op);
2811         }
2812 }
2813
2814 static void
2815 create_folder_performer (gboolean canceled, 
2816                          GError *err,
2817                          GtkWindow *parent_window, 
2818                          TnyAccount *account, 
2819                          gpointer user_data)
2820 {
2821         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2822
2823         if (canceled || err) {
2824                 goto frees;
2825         }
2826
2827         /* Run the new folder dialog */
2828         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2829
2830  frees:
2831         g_object_unref (parent_folder);
2832 }
2833
2834 static void
2835 modest_ui_actions_create_folder(GtkWidget *parent_window,
2836                                 GtkWidget *folder_view)
2837 {
2838         TnyFolderStore *parent_folder;
2839
2840         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2841         
2842         if (parent_folder) {
2843                 /* The parent folder will be freed in the callback */
2844                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2845                                                                TRUE,
2846                                                                parent_folder,
2847                                                                create_folder_performer, 
2848                                                                parent_folder);
2849         }
2850 }
2851
2852 void 
2853 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2854 {
2855         GtkWidget *folder_view;
2856         
2857         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2858
2859         folder_view = modest_main_window_get_child_widget (main_window,
2860                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2861         if (!folder_view)
2862                 return;
2863
2864         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2865 }
2866
2867 static void
2868 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2869                                                gpointer user_data)
2870 {
2871         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2872         const GError *error = NULL;
2873         const gchar *message = NULL;
2874         
2875         /* Get error message */
2876         error = modest_mail_operation_get_error (mail_op);
2877         if (!error)
2878                 g_return_if_reached ();
2879
2880         switch (error->code) {
2881         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2882                 message = _CS("ckdg_ib_folder_already_exists");
2883                 break;
2884         default:
2885                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2886                            error->code, error->message);
2887                 return;
2888         }
2889
2890         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2891 }
2892
2893 typedef struct {
2894         TnyFolderStore *folder;
2895         gchar *new_name;
2896 } RenameFolderInfo;
2897
2898 static void
2899 on_rename_folder_cb (ModestMailOperation *mail_op, 
2900                      TnyFolder *new_folder,
2901                      gpointer user_data)
2902 {
2903         /* Select now */
2904         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2905                                           new_folder, FALSE);
2906 }
2907
2908 static void
2909 on_rename_folder_performer (gboolean canceled, 
2910                             GError *err, 
2911                             GtkWindow *parent_window, 
2912                             TnyAccount *account, 
2913                             gpointer user_data)
2914 {
2915         ModestMailOperation *mail_op = NULL;
2916         GtkTreeSelection *sel = NULL;
2917         GtkWidget *folder_view = NULL;
2918         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2919
2920         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2921
2922                 folder_view = modest_main_window_get_child_widget (
2923                                 MODEST_MAIN_WINDOW (parent_window),
2924                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2925
2926                 mail_op = 
2927                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2928                                         modest_ui_actions_rename_folder_error_handler,
2929                                         parent_window, NULL);
2930
2931                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2932                                 mail_op);
2933
2934                 /* Clear the headers view */
2935                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2936                 gtk_tree_selection_unselect_all (sel);
2937
2938                 /* Actually rename the folder */
2939                 modest_mail_operation_rename_folder (mail_op,
2940                                                      TNY_FOLDER (data->folder),
2941                                                      (const gchar *) (data->new_name),
2942                                                      on_rename_folder_cb,
2943                                                      folder_view);
2944         }
2945
2946         g_object_unref (mail_op);
2947         g_free (data->new_name);
2948         g_free (data);
2949 }
2950
2951 void 
2952 modest_ui_actions_on_rename_folder (GtkAction *action,
2953                                      ModestMainWindow *main_window)
2954 {
2955         TnyFolderStore *folder;
2956         GtkWidget *folder_view;
2957         GtkWidget *header_view; 
2958
2959         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2960
2961         folder_view = modest_main_window_get_child_widget (main_window,
2962                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2963         if (!folder_view)
2964                 return;
2965
2966         header_view = modest_main_window_get_child_widget (main_window,
2967                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2968         
2969         if (!header_view)
2970                 return;
2971
2972         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2973
2974         if (!folder)
2975                 return;
2976
2977         if (TNY_IS_FOLDER (folder)) {
2978                 gchar *folder_name;
2979                 gint response;
2980                 const gchar *current_name;
2981                 TnyFolderStore *parent;
2982                 gboolean do_rename = TRUE;
2983
2984                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2985                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2986                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2987                                                                      parent, current_name, 
2988                                                                      &folder_name);
2989                 g_object_unref (parent);
2990
2991                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2992                         do_rename = FALSE;
2993                 } else {
2994                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2995                         rename_folder_data->folder = folder;
2996                         rename_folder_data->new_name = folder_name;
2997                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
2998                                         folder, on_rename_folder_performer, rename_folder_data);
2999                 }
3000         }
3001         g_object_unref (folder);
3002 }
3003
3004 static void
3005 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3006                                                gpointer user_data)
3007 {
3008         GObject *win = modest_mail_operation_get_source (mail_op);
3009
3010         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3011                                                 _("mail_in_ui_folder_delete_error"));
3012         g_object_unref (win);
3013 }
3014
3015 typedef struct {
3016         TnyFolderStore *folder;
3017         gboolean move_to_trash;
3018 } DeleteFolderInfo;
3019
3020 static void
3021 on_delete_folder_cb (gboolean canceled, 
3022                   GError *err,
3023                   GtkWindow *parent_window, 
3024                   TnyAccount *account, 
3025                   gpointer user_data)
3026 {
3027         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3028         GtkWidget *folder_view;
3029         ModestMailOperation *mail_op;
3030         GtkTreeSelection *sel;
3031         
3032         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3033                 g_object_unref (G_OBJECT (info->folder));
3034                 g_free (info);
3035                 return;
3036         }
3037         
3038         folder_view = modest_main_window_get_child_widget (
3039                         MODEST_MAIN_WINDOW (parent_window),
3040                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3041
3042         /* Unselect the folder before deleting it to free the headers */
3043         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3044         gtk_tree_selection_unselect_all (sel);
3045
3046         /* Create the mail operation */
3047         mail_op =
3048                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3049                                 modest_ui_actions_delete_folder_error_handler,
3050                                 NULL, NULL);
3051
3052         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3053                         mail_op);
3054         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3055         
3056         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3057
3058         g_object_unref (G_OBJECT (mail_op));
3059         g_object_unref (G_OBJECT (info->folder));
3060         g_free (info);
3061 }
3062
3063 static void
3064 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3065 {
3066         TnyFolderStore *folder;
3067         GtkWidget *folder_view;
3068         gint response;
3069         gchar *message;
3070         
3071         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3072
3073         folder_view = modest_main_window_get_child_widget (main_window,
3074                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3075         if (!folder_view)
3076                 return;
3077
3078         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3079
3080         /* Show an error if it's an account */
3081         if (!TNY_IS_FOLDER (folder)) {
3082                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3083                                                         _("mail_in_ui_folder_delete_error"));
3084                 g_object_unref (G_OBJECT (folder));
3085                 return;
3086         }
3087
3088         /* Ask the user */      
3089         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3090                                     tny_folder_get_name (TNY_FOLDER (folder)));
3091         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3092                                                             (const gchar *) message);
3093         g_free (message);
3094
3095         if (response == GTK_RESPONSE_OK) {
3096                 DeleteFolderInfo *info;
3097                 info = g_new0(DeleteFolderInfo, 1);
3098                 info->folder = folder;
3099                 info->move_to_trash = move_to_trash;
3100                 g_object_ref (G_OBJECT (info->folder));
3101                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3102                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3103                                                                TRUE,
3104                                                                TNY_FOLDER_STORE (account), 
3105                                                                on_delete_folder_cb, info);
3106                 g_object_unref (account);
3107         }
3108         g_object_unref (G_OBJECT (folder));
3109 }
3110
3111 void 
3112 modest_ui_actions_on_delete_folder (GtkAction *action,
3113                                      ModestMainWindow *main_window)
3114 {
3115         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3116         
3117         delete_folder (main_window, FALSE);
3118 }
3119
3120 void 
3121 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3122 {
3123         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3124         
3125         delete_folder (main_window, TRUE);
3126 }
3127
3128
3129 void
3130 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3131                                          const gchar* server_account_name,
3132                                          gchar **username,
3133                                          gchar **password, 
3134                                          gboolean *cancel, 
3135                                          gboolean *remember,
3136                                          ModestMainWindow *main_window)
3137 {
3138         g_return_if_fail(server_account_name);
3139         gboolean completed = FALSE;
3140         
3141         /* Initalize output parameters: */
3142         if (cancel)
3143                 *cancel = FALSE;
3144                 
3145         if (remember)
3146                 *remember = TRUE;
3147                 
3148 #ifdef MODEST_PLATFORM_MAEMO
3149         /* Maemo uses a different (awkward) button order,
3150          * It should probably just use gtk_alternative_dialog_button_order ().
3151          */
3152         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3153                                               NULL,
3154                                               GTK_DIALOG_MODAL,
3155                                               _("mcen_bd_dialog_ok"),
3156                                               GTK_RESPONSE_ACCEPT,
3157                                               _("mcen_bd_dialog_cancel"),
3158                                               GTK_RESPONSE_REJECT,
3159                                               NULL);
3160 #else
3161         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3162                                               NULL,
3163                                               GTK_DIALOG_MODAL,
3164                                               GTK_STOCK_CANCEL,
3165                                               GTK_RESPONSE_REJECT,
3166                                               GTK_STOCK_OK,
3167                                               GTK_RESPONSE_ACCEPT,
3168                                               NULL);
3169 #endif /* MODEST_PLATFORM_MAEMO */
3170
3171         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3172         
3173         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3174                 modest_runtime_get_account_mgr(), server_account_name);
3175         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3176                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3177                 if (cancel)
3178                         *cancel = TRUE;
3179                 return;
3180         }
3181         
3182         /* This causes a warning because the logical ID has no %s in it, 
3183          * though the translation does, but there is not much we can do about that: */
3184         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3185         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3186                             FALSE, FALSE, 0);
3187         g_free (txt);
3188         g_free (server_name);
3189         server_name = NULL;
3190
3191         /* username: */
3192         gchar *initial_username = modest_account_mgr_get_server_account_username (
3193                 modest_runtime_get_account_mgr(), server_account_name);
3194         
3195         GtkWidget *entry_username = gtk_entry_new ();
3196         if (initial_username)
3197                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3198         /* Dim this if a connection has ever succeeded with this username,
3199          * as per the UI spec: */
3200         const gboolean username_known = 
3201                 modest_account_mgr_get_server_account_username_has_succeeded(
3202                         modest_runtime_get_account_mgr(), server_account_name);
3203         gtk_widget_set_sensitive (entry_username, !username_known);
3204         
3205 #ifdef MODEST_PLATFORM_MAEMO
3206         /* Auto-capitalization is the default, so let's turn it off: */
3207         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3208         
3209         /* Create a size group to be used by all captions.
3210          * Note that HildonCaption does not create a default size group if we do not specify one.
3211          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3212         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3213         
3214         GtkWidget *caption = hildon_caption_new (sizegroup, 
3215                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3216         gtk_widget_show (entry_username);
3217         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3218                 FALSE, FALSE, MODEST_MARGIN_HALF);
3219         gtk_widget_show (caption);
3220 #else 
3221         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3222                             TRUE, FALSE, 0);
3223 #endif /* MODEST_PLATFORM_MAEMO */      
3224                             
3225         /* password: */
3226         GtkWidget *entry_password = gtk_entry_new ();
3227         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3228         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3229         
3230 #ifdef MODEST_PLATFORM_MAEMO
3231         /* Auto-capitalization is the default, so let's turn it off: */
3232         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3233                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3234         
3235         caption = hildon_caption_new (sizegroup, 
3236                 _("mail_fi_password"), entry_password, NULL