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