8d618d3b256c37a47d37b6fd9d63d47092aaecf7
[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         gtk_widget_show_all (GTK_WIDGET (msg_win));
793
794 cleanup:
795         g_free (from_str);
796         g_free (signature);
797         g_free (body);
798         g_free (account_name);
799         if (account) g_object_unref (G_OBJECT(account));
800         if (folder) g_object_unref (G_OBJECT(folder));
801         if (msg_win) g_object_unref (G_OBJECT(msg_win));
802         if (msg) g_object_unref (G_OBJECT(msg));
803 }
804
805 void
806 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
807 {
808         /* if there are no accounts yet, just show the wizard */
809         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
810                 if (!modest_ui_actions_run_account_setup_wizard (win))
811                         return;
812                 
813         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
814 }
815
816 void
817 modest_ui_actions_on_new_msg_or_folder (GtkAction *action, ModestWindow *win)
818 {
819         g_return_if_fail (MODEST_IS_WINDOW (win));
820
821         /* Check first if the folder view has the focus */
822         if (MODEST_IS_MAIN_WINDOW (win)) {
823                 GtkWidget *w;
824                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
825                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
826                 if (gtk_widget_is_focus (w)) {
827                         modest_ui_actions_on_new_folder (action, MODEST_MAIN_WINDOW(win));
828                         return;
829                 }
830         }
831
832         modest_ui_actions_on_new_msg (action, win);
833 }
834
835
836 gboolean 
837 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
838                                        TnyHeader *header,
839                                        TnyMsg *msg)
840 {
841         ModestMailOperationStatus status;
842
843         /* If there is no message or the operation was not successful */
844         status = modest_mail_operation_get_status (mail_op);
845         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
846
847                 /* Remove the header from the preregistered uids */
848                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
849                                                      header);
850
851                 return FALSE;
852         }
853
854         return TRUE;
855 }
856
857 static void
858 open_msg_cb (ModestMailOperation *mail_op, 
859              TnyHeader *header,  
860              gboolean canceled,
861              TnyMsg *msg, 
862              GError *err,
863              gpointer user_data)
864 {
865         ModestWindowMgr *mgr = NULL;
866         ModestWindow *parent_win = NULL;
867         ModestWindow *win = NULL;
868         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
869         gchar *account = NULL;
870         TnyFolder *folder;
871         gboolean open_in_editor = FALSE;
872         
873         /* Do nothing if there was any problem with the mail
874            operation. The error will be shown by the error_handler of
875            the mail operation */
876         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
877                 return;
878
879         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
880         folder = tny_header_get_folder (header);
881
882         /* Mark header as read */
883         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
884
885         /* Gets folder type (OUTBOX headers will be opened in edit window */
886         if (modest_tny_folder_is_local_folder (folder)) {
887                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
888                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
889                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
890         }
891
892                 
893         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
894                 TnyTransportAccount *traccount = NULL;
895                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
896                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
897                 if (traccount) {
898                         ModestTnySendQueue *send_queue = NULL;
899                         ModestTnySendQueueStatus status;
900                         char *msg_id;
901                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
902                                                    TNY_ACCOUNT(traccount)));
903                         send_queue = modest_runtime_get_send_queue(traccount);
904                         msg_id = modest_tny_send_queue_get_msg_id (header);
905                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
906                         /* Only open messages in outbox with the editor if they are in Failed state */
907                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
908                                 open_in_editor = TRUE;
909                         }
910                         g_free(msg_id);
911                         g_object_unref(traccount);
912                 } else {
913                         g_warning("Cannot get transport account for message in outbox!!");
914                 }
915         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
916                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
917         }
918
919         /* Get account */
920         if (!account)
921                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
922         if (!account)
923                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
924         
925         if (open_in_editor) {
926                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
927                 const gchar *from_header = NULL;
928
929                 from_header = tny_header_get_from (header);
930
931                 /* we cannot edit without a valid account... */
932                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
933                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
934                                 goto cleanup;
935                 }
936                 
937                 if (from_header) {
938                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
939                         GSList *node = NULL;
940                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
941                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
942                                 
943                                 if (from && (strcmp (from_header, from) == 0)) {
944                                         g_free (account);
945                                         account = g_strdup (node->data);
946                                         g_free (from);
947                                         break;
948                                 }
949                                 g_free (from);
950                         }
951                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
952                         g_slist_free (accounts);
953                 }
954
955                 win = modest_msg_edit_window_new (msg, account, TRUE);
956
957
958                 /* Show banner */
959                 modest_platform_information_banner_with_timeout
960                         (NULL, NULL, _("mail_ib_opening_draft_message"), 1200);
961
962         } else {
963                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
964                 
965                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
966                         GtkWidget *header_view;
967                         GtkTreeSelection *sel;
968                         GList *sel_list = NULL;
969                         GtkTreeModel *model;
970                         
971                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
972                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
973
974                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
975                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
976
977                         if (sel_list != NULL) {
978                                 GtkTreeRowReference *row_reference;
979
980                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
981                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
982                                 g_list_free (sel_list);
983                                 
984                                 win = modest_msg_view_window_new_with_header_model (
985                                                 msg, account, (const gchar*) uid,
986                                                 model, row_reference);
987                                 gtk_tree_row_reference_free (row_reference);
988                         } else {
989                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
990                         }
991                 } else {
992                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
993                 }
994                 g_free (uid);
995         }
996         
997         /* Register and show new window */
998         if (win != NULL) {
999                 mgr = modest_runtime_get_window_mgr ();
1000                 modest_window_mgr_register_window (mgr, win);
1001                 g_object_unref (win);
1002                 gtk_widget_show_all (GTK_WIDGET(win));
1003         }
1004
1005         /* Update toolbar dimming state */
1006         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1007                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1008         }
1009
1010 cleanup:
1011         /* Free */
1012         g_free(account);
1013         g_object_unref (parent_win);
1014         g_object_unref (folder);
1015 }
1016
1017 void
1018 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1019                                                gpointer user_data)
1020 {
1021         const GError *error;
1022         GObject *win = NULL;
1023         const gchar *err_msg = (const gchar *) user_data;
1024
1025         win = modest_mail_operation_get_source (mail_op);
1026         error = modest_mail_operation_get_error (mail_op);
1027
1028         /* Show error */
1029         modest_platform_run_information_dialog ((GtkWindow *) win, err_msg);
1030
1031         if (win)
1032                 g_object_unref (win);
1033 }
1034
1035 /**
1036  * Returns the account a list of headers belongs to. It returns a
1037  * *new* reference so don't forget to unref it
1038  */
1039 static TnyAccount*
1040 get_account_from_header_list (TnyList *headers)
1041 {
1042         TnyAccount *account = NULL;
1043
1044         if (tny_list_get_length (headers) > 0) {
1045                 TnyIterator *iter = tny_list_create_iterator (headers);
1046                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1047                 TnyFolder *folder = tny_header_get_folder (header);
1048                 account = tny_folder_get_account (folder);
1049                 g_object_unref (folder);
1050                 g_object_unref (header);
1051                 g_object_unref (iter);
1052         }
1053         return account;
1054 }
1055
1056 static void 
1057 foreach_unregister_headers (gpointer data,
1058                             gpointer user_data)
1059 {
1060         ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1061         TnyHeader *header = TNY_HEADER (data);
1062
1063         modest_window_mgr_unregister_header (mgr, header);
1064 }
1065
1066 static void
1067 open_msgs_performer(gboolean canceled, 
1068                     GError *err,
1069                     GtkWindow *parent_window,
1070                     TnyAccount *account,
1071                     gpointer user_data)
1072 {
1073         ModestMailOperation *mail_op = NULL;
1074         const gchar *proto_name;
1075         gchar *error_msg;
1076         ModestTransportStoreProtocol proto;
1077         TnyList *not_opened_headers;
1078         TnyConnectionStatus status;
1079
1080         not_opened_headers = TNY_LIST (user_data);
1081
1082         status = tny_account_get_connection_status (account);
1083         if (err || canceled) {
1084                 /* Unregister the already registered headers */
1085                 tny_list_foreach (not_opened_headers, foreach_unregister_headers, 
1086                                   modest_runtime_get_window_mgr ());
1087                 goto clean;
1088         }
1089
1090         /* Get the error message depending on the protocol */
1091         proto_name = tny_account_get_proto (account);
1092         if (proto_name != NULL) {
1093                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1094         } else {
1095                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1096         }
1097         
1098         /* Create the error messages */
1099         if (tny_list_get_length (not_opened_headers) == 1) {
1100                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1101                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1102                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1103                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1104                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1105                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1106                                                      tny_header_get_subject (header));
1107                         g_object_unref (header);
1108                         g_object_unref (iter);
1109                 } else {
1110                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1111                 }
1112         } else {
1113                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1114         }
1115
1116         /* Create the mail operation */
1117         mail_op = 
1118                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1119                                                                modest_ui_actions_get_msgs_full_error_handler,
1120                                                                error_msg, g_free);
1121         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1122                                          mail_op);
1123                 
1124         modest_mail_operation_get_msgs_full (mail_op,
1125                                              not_opened_headers,
1126                                              open_msg_cb,
1127                                              NULL,
1128                                              NULL);
1129
1130         /* Frees */
1131  clean:
1132         if (mail_op)
1133                 g_object_unref (mail_op);
1134         g_object_unref (not_opened_headers);
1135         g_object_unref (account);
1136 }
1137
1138 /*
1139  * This function is used by both modest_ui_actions_on_open and
1140  * modest_ui_actions_on_header_activated. This way we always do the
1141  * same when trying to open messages.
1142  */
1143 static void
1144 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1145 {
1146         ModestWindowMgr *mgr = NULL;
1147         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1148         TnyList *not_opened_headers = NULL;
1149         TnyHeaderFlags flags = 0;
1150         TnyAccount *account;
1151         gint uncached_msgs = 0;
1152                 
1153         g_return_if_fail (headers != NULL);
1154
1155         /* Check that only one message is selected for opening */
1156         if (tny_list_get_length (headers) != 1) {
1157                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1158                                                         _("mcen_ib_select_one_message"));
1159                 return;
1160         }
1161
1162         mgr = modest_runtime_get_window_mgr ();
1163         iter = tny_list_create_iterator (headers);
1164
1165         /* Get the account */
1166         account = get_account_from_header_list (headers);
1167         
1168         /* Look if we already have a message view for each header. If
1169            true, then remove the header from the list of headers to
1170            open */
1171         not_opened_headers = tny_simple_list_new ();
1172         while (!tny_iterator_is_done (iter)) {
1173
1174                 ModestWindow *window = NULL;
1175                 TnyHeader *header = NULL;
1176                 gboolean found = FALSE;
1177                 
1178                 header = TNY_HEADER (tny_iterator_get_current (iter));
1179                 if (header)
1180                         flags = tny_header_get_flags (header);
1181
1182                 window = NULL;
1183                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1184                 
1185                 /* Do not open again the message and present the
1186                    window to the user */
1187                 if (found) {
1188                         if (window)
1189                                 gtk_window_present (GTK_WINDOW (window));
1190                         else
1191                                 /* the header has been registered already, we don't do
1192                                  * anything but wait for the window to come up*/
1193                                 g_debug ("header %p already registered, waiting for window", header);
1194                 } else {
1195                         tny_list_append (not_opened_headers, G_OBJECT (header));
1196                 }
1197
1198                 if (header)
1199                         g_object_unref (header);
1200
1201                 tny_iterator_next (iter);
1202         }
1203         g_object_unref (iter);
1204         iter = NULL;
1205
1206         /* Open each message */
1207         if (tny_list_get_length (not_opened_headers) == 0)
1208                 goto cleanup;
1209         
1210         /* If some messages would have to be downloaded, ask the user to 
1211          * make a connection. It's generally easier to do this here (in the mainloop) 
1212          * than later in a thread:
1213          */
1214         if (tny_list_get_length (not_opened_headers) > 0) {
1215                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1216
1217                 if (uncached_msgs > 0) {
1218                         /* Allways download if we are online. */
1219                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1220                                 gint response;
1221
1222                                 /* If ask for user permission to download the messages */
1223                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1224                                                                                     ngettext("mcen_nc_get_msg",
1225                                                                                              "mcen_nc_get_msgs",
1226                                                                                              uncached_msgs));
1227
1228                                 /* End if the user does not want to continue */
1229                                 if (response == GTK_RESPONSE_CANCEL)
1230                                         goto cleanup;
1231                         }
1232                 }
1233         }
1234         
1235         /* Register the headers before actually creating the windows: */
1236         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1237         while (!tny_iterator_is_done (iter_not_opened)) {
1238                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1239                 if (header) {
1240                         modest_window_mgr_register_header (mgr, header, NULL);
1241                         g_object_unref (header);
1242                 }
1243                 tny_iterator_next (iter_not_opened);
1244         }
1245         g_object_unref (iter_not_opened);
1246         iter_not_opened = NULL;
1247
1248         /* Connect to the account and perform */
1249         if (uncached_msgs > 0) {
1250                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account), 
1251                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1252         } else {
1253                 /* Call directly the performer, do not need to connect */
1254                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1255                                      g_object_ref (not_opened_headers));
1256         }
1257 cleanup:
1258         /* Clean */
1259         if (account)
1260                 g_object_unref (account);
1261         if (not_opened_headers)
1262                 g_object_unref (not_opened_headers);
1263 }
1264
1265 void
1266 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1267 {
1268         TnyList *headers;
1269
1270         /* Get headers */
1271         headers = get_selected_headers (win);
1272         if (!headers)
1273                 return;
1274
1275         /* Open them */
1276         open_msgs_from_headers (headers, win);
1277
1278         g_object_unref(headers);
1279 }
1280
1281
1282 static void
1283 free_reply_forward_helper (gpointer data)
1284 {
1285         ReplyForwardHelper *helper;
1286
1287         helper = (ReplyForwardHelper *) data;
1288         g_free (helper->account_name);
1289         g_slice_free (ReplyForwardHelper, helper);
1290 }
1291
1292 static void
1293 reply_forward_cb (ModestMailOperation *mail_op,  
1294                   TnyHeader *header, 
1295                   gboolean canceled,
1296                   TnyMsg *msg,
1297                   GError *err,
1298                   gpointer user_data)
1299 {
1300         TnyMsg *new_msg;
1301         ReplyForwardHelper *rf_helper;
1302         ModestWindow *msg_win = NULL;
1303         ModestEditType edit_type;
1304         gchar *from = NULL;
1305         TnyAccount *account = NULL;
1306         ModestWindowMgr *mgr = NULL;
1307         gchar *signature = NULL;
1308         gboolean use_signature;
1309
1310         /* If there was any error. The mail operation could be NULL,
1311            this means that we already have the message downloaded and
1312            that we didn't do a mail operation to retrieve it */
1313         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1314                 return;
1315                         
1316         g_return_if_fail (user_data != NULL);
1317         rf_helper = (ReplyForwardHelper *) user_data;
1318
1319         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1320                                                    rf_helper->account_name);
1321         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1322                                                       rf_helper->account_name, 
1323                                                       &use_signature);
1324
1325         /* Create reply mail */
1326         switch (rf_helper->action) {
1327         case ACTION_REPLY:
1328                 new_msg = 
1329                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1330                                                          rf_helper->reply_forward_type,
1331                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1332                 break;
1333         case ACTION_REPLY_TO_ALL:
1334                 new_msg = 
1335                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1336                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1337                 edit_type = MODEST_EDIT_TYPE_REPLY;
1338                 break;
1339         case ACTION_FORWARD:
1340                 new_msg = 
1341                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1342                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1343                 break;
1344         default:
1345                 g_return_if_reached ();
1346                 return;
1347         }
1348
1349         g_free (signature);
1350
1351         if (!new_msg) {
1352                 g_printerr ("modest: failed to create message\n");
1353                 goto cleanup;
1354         }
1355
1356         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1357                                                                        rf_helper->account_name,
1358                                                                        TNY_ACCOUNT_TYPE_STORE);
1359         if (!account) {
1360                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1361                 goto cleanup;
1362         }
1363
1364         /* Create and register the windows */
1365         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1366         mgr = modest_runtime_get_window_mgr ();
1367         modest_window_mgr_register_window (mgr, msg_win);
1368
1369         if (rf_helper->parent_window != NULL) {
1370                 gdouble parent_zoom;
1371
1372                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1373                 modest_window_set_zoom (msg_win, parent_zoom);
1374         }
1375
1376         /* Show edit window */
1377         gtk_widget_show_all (GTK_WIDGET (msg_win));
1378
1379 cleanup:
1380         if (msg_win)
1381                 g_object_unref (msg_win);
1382         if (new_msg)
1383                 g_object_unref (G_OBJECT (new_msg));
1384         if (account)
1385                 g_object_unref (G_OBJECT (account));
1386 /*      g_object_unref (msg); */
1387         free_reply_forward_helper (rf_helper);
1388 }
1389
1390 /* Checks a list of headers. If any of them are not currently
1391  * downloaded (CACHED) then returns TRUE else returns FALSE.
1392  */
1393 static gint
1394 header_list_count_uncached_msgs (TnyList *header_list)
1395 {
1396         TnyIterator *iter;
1397         gint uncached_messages = 0;
1398
1399         iter = tny_list_create_iterator (header_list);
1400         while (!tny_iterator_is_done (iter)) {
1401                 TnyHeader *header;
1402
1403                 header = TNY_HEADER (tny_iterator_get_current (iter));
1404                 if (header) {
1405                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1406                                 uncached_messages ++;
1407                         g_object_unref (header);
1408                 }
1409
1410                 tny_iterator_next (iter);
1411         }
1412         g_object_unref (iter);
1413
1414         return uncached_messages;
1415 }
1416
1417 /* Returns FALSE if the user does not want to download the
1418  * messages. Returns TRUE if the user allowed the download.
1419  */
1420 static gboolean
1421 connect_to_get_msg (ModestWindow *win,
1422                     gint num_of_uncached_msgs,
1423                     TnyAccount *account)
1424 {
1425         GtkResponseType response;
1426
1427         /* Allways download if we are online. */
1428         if (tny_device_is_online (modest_runtime_get_device ()))
1429                 return TRUE;
1430
1431         /* If offline, then ask for user permission to download the messages */
1432         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1433                         ngettext("mcen_nc_get_msg",
1434                         "mcen_nc_get_msgs",
1435                         num_of_uncached_msgs));
1436
1437         if (response == GTK_RESPONSE_CANCEL)
1438                 return FALSE;
1439
1440         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1441 }
1442
1443 /*
1444  * Common code for the reply and forward actions
1445  */
1446 static void
1447 reply_forward (ReplyForwardAction action, ModestWindow *win)
1448 {
1449         ModestMailOperation *mail_op = NULL;
1450         TnyList *header_list = NULL;
1451         ReplyForwardHelper *rf_helper = NULL;
1452         guint reply_forward_type;
1453         gboolean continue_download = TRUE;
1454         gboolean do_retrieve = TRUE;
1455         
1456         g_return_if_fail (MODEST_IS_WINDOW(win));
1457
1458         /* we need an account when editing */
1459         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1460                 if (!modest_ui_actions_run_account_setup_wizard (win))
1461                         return;
1462         }
1463         
1464         header_list = get_selected_headers (win);
1465         if (!header_list)
1466                 return;
1467
1468         reply_forward_type = 
1469                 modest_conf_get_int (modest_runtime_get_conf (),
1470                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1471                                      NULL);
1472
1473         /* check if we need to download msg before asking about it */
1474         do_retrieve = (action == ACTION_FORWARD) ||
1475                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1476
1477         if (do_retrieve){
1478                 gint num_of_unc_msgs;
1479
1480                 /* check that the messages have been previously downloaded */
1481                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1482                 /* If there are any uncached message ask the user
1483                  * whether he/she wants to download them. */
1484                 if (num_of_unc_msgs) {
1485                         TnyAccount *account = get_account_from_header_list (header_list);
1486                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1487                         g_object_unref (account);
1488                 }
1489         }
1490
1491         if (!continue_download) {
1492                 g_object_unref (header_list);
1493                 return;
1494         }
1495         
1496         /* We assume that we can only select messages of the
1497            same folder and that we reply all of them from the
1498            same account. In fact the interface currently only
1499            allows single selection */
1500         
1501         /* Fill helpers */
1502         rf_helper = g_slice_new0 (ReplyForwardHelper);
1503         rf_helper->reply_forward_type = reply_forward_type;
1504         rf_helper->action = action;
1505         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1506         
1507         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1508                 rf_helper->parent_window = GTK_WIDGET (win);
1509         if (!rf_helper->account_name)
1510                 rf_helper->account_name =
1511                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1512
1513         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1514                 TnyMsg *msg;
1515                 TnyHeader *header;
1516                 /* Get header and message. Do not free them here, the
1517                    reply_forward_cb must do it */
1518                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1519                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1520                 if (!msg || !header) {
1521                         if (msg)
1522                                 g_object_unref (msg);
1523                         g_printerr ("modest: no message found\n");
1524                         return;
1525                 } else {
1526                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1527                 }
1528                 if (header)
1529                         g_object_unref (header);
1530         } else {
1531                 TnyHeader *header;
1532                 TnyIterator *iter;
1533
1534                 /* Only reply/forward to one message */
1535                 iter = tny_list_create_iterator (header_list);
1536                 header = TNY_HEADER (tny_iterator_get_current (iter));
1537                 g_object_unref (iter);
1538
1539                 if (header) {
1540                         /* Retrieve messages */
1541                         if (do_retrieve) {
1542                                 mail_op = 
1543                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1544                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1545                                                                                        NULL, NULL);
1546                                 modest_mail_operation_queue_add (
1547                                         modest_runtime_get_mail_operation_queue (), mail_op);
1548                                 
1549                                 modest_mail_operation_get_msg (mail_op,
1550                                                                header,
1551                                                                reply_forward_cb,
1552                                                                rf_helper);
1553                                 /* Clean */
1554                                 g_object_unref(mail_op);
1555                         } else {
1556                                 /* we put a ref here to prevent double unref as the reply
1557                                  * forward callback unrefs the header at its end */
1558                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1559                         }
1560
1561
1562                         g_object_unref (header);
1563                 }
1564
1565         }
1566
1567         /* Free */
1568         g_object_unref (header_list);
1569 }
1570
1571 void
1572 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1573 {
1574         g_return_if_fail (MODEST_IS_WINDOW(win));
1575
1576         reply_forward (ACTION_REPLY, win);
1577 }
1578
1579 void
1580 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1581 {
1582         g_return_if_fail (MODEST_IS_WINDOW(win));
1583
1584         reply_forward (ACTION_FORWARD, win);
1585 }
1586
1587 void
1588 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1589 {
1590         g_return_if_fail (MODEST_IS_WINDOW(win));
1591
1592         reply_forward (ACTION_REPLY_TO_ALL, win);
1593 }
1594
1595 void 
1596 modest_ui_actions_on_next (GtkAction *action, 
1597                            ModestWindow *window)
1598 {
1599         if (MODEST_IS_MAIN_WINDOW (window)) {
1600                 GtkWidget *header_view;
1601
1602                 header_view = modest_main_window_get_child_widget (
1603                                 MODEST_MAIN_WINDOW(window),
1604                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1605                 if (!header_view)
1606                         return;
1607         
1608                 modest_header_view_select_next (
1609                                 MODEST_HEADER_VIEW(header_view)); 
1610         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1611                 modest_msg_view_window_select_next_message (
1612                                 MODEST_MSG_VIEW_WINDOW (window));
1613         } else {
1614                 g_return_if_reached ();
1615         }
1616 }
1617
1618 void 
1619 modest_ui_actions_on_prev (GtkAction *action, 
1620                            ModestWindow *window)
1621 {
1622         g_return_if_fail (MODEST_IS_WINDOW(window));
1623
1624         if (MODEST_IS_MAIN_WINDOW (window)) {
1625                 GtkWidget *header_view;
1626                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1627                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1628                 if (!header_view)
1629                         return;
1630                 
1631                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1632         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1633                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1634         } else {
1635                 g_return_if_reached ();
1636         }
1637 }
1638
1639 void 
1640 modest_ui_actions_on_sort (GtkAction *action, 
1641                            ModestWindow *window)
1642 {
1643         g_return_if_fail (MODEST_IS_WINDOW(window));
1644
1645         if (MODEST_IS_MAIN_WINDOW (window)) {
1646                 GtkWidget *header_view;
1647                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1648                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1649                 if (!header_view) {
1650                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1651
1652                         return;
1653                 }
1654
1655                 /* Show sorting dialog */
1656                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1657         }
1658 }
1659
1660 static void
1661 new_messages_arrived (ModestMailOperation *self, 
1662                       TnyList *new_headers,
1663                       gpointer user_data)
1664 {
1665         GObject *source;
1666         gboolean show_visual_notifications;
1667
1668         source = modest_mail_operation_get_source (self);
1669         show_visual_notifications = (source) ? FALSE : TRUE;
1670         if (source)
1671                 g_object_unref (source);
1672
1673         /* Notify new messages have been downloaded. If the
1674            send&receive was invoked by the user then do not show any
1675            visual notification, only play a sound and activate the LED
1676            (for the Maemo version) */
1677         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0))
1678                 modest_platform_on_new_headers_received (new_headers, 
1679                                                          show_visual_notifications);
1680
1681 }
1682
1683 gboolean
1684 retrieve_all_messages_cb (GObject *source,
1685                           guint num_msgs,
1686                           guint retrieve_limit)
1687 {
1688         GtkWindow *window;
1689         gchar *msg;
1690         gint response;
1691
1692         window = GTK_WINDOW (source);
1693         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1694                                num_msgs, retrieve_limit);
1695
1696         /* Ask the user if they want to retrieve all the messages */
1697         response = 
1698                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1699                                                                       _("mcen_bd_get_all"),
1700                                                                       _("mcen_bd_newest_only"));
1701         /* Free and return */
1702         g_free (msg);
1703         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1704 }
1705
1706 typedef struct {
1707         TnyAccount *account;
1708         ModestWindow *win;
1709         gchar *account_name;
1710 } SendReceiveInfo;
1711
1712 static void
1713 do_send_receive_performer (gboolean canceled, 
1714                            GError *err,
1715                            GtkWindow *parent_window, 
1716                            TnyAccount *account, 
1717                            gpointer user_data)
1718 {
1719         ModestMailOperation *mail_op;
1720         SendReceiveInfo *info;
1721
1722         info = (SendReceiveInfo *) user_data;
1723
1724         if (err || canceled) {
1725                 goto clean;
1726         }
1727
1728         /* Set send/receive operation in progress */    
1729         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1730                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1731         }
1732         
1733         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1734                                                                  modest_ui_actions_send_receive_error_handler,
1735                                                                  NULL, NULL);
1736
1737         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1738                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1739                                   G_CALLBACK (on_send_receive_finished), 
1740                                   info->win);
1741
1742         /* Send & receive. */
1743         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1744         modest_mail_operation_update_account (mail_op, info->account_name, (info->win) ? FALSE : TRUE,
1745                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1746                                               new_messages_arrived, info->win);
1747         g_object_unref (G_OBJECT (mail_op));
1748         
1749  clean:
1750         /* Frees */
1751         if (info->account_name)
1752                 g_free (info->account_name);
1753         if (info->win)
1754                 g_object_unref (info->win);
1755         if (info->account)
1756                 g_object_unref (info->account);
1757         g_slice_free (SendReceiveInfo, info);
1758 }
1759
1760 /*
1761  * This function performs the send & receive required actions. The
1762  * window is used to create the mail operation. Typically it should
1763  * always be the main window, but we pass it as argument in order to
1764  * be more flexible.
1765  */
1766 void
1767 modest_ui_actions_do_send_receive (const gchar *account_name, 
1768                                    gboolean force_connection,
1769                                    ModestWindow *win)
1770 {
1771         gchar *acc_name = NULL;
1772         SendReceiveInfo *info;
1773         ModestTnyAccountStore *acc_store;
1774
1775         /* If no account name was provided then get the current account, and if
1776            there is no current account then pick the default one: */
1777         if (!account_name) {
1778                 if (win)
1779                         acc_name = g_strdup (modest_window_get_active_account (win));
1780                 if (!acc_name)
1781                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1782                 if (!acc_name) {
1783                         g_printerr ("modest: cannot get default account\n");
1784                         return;
1785                 }
1786         } else {
1787                 acc_name = g_strdup (account_name);
1788         }
1789
1790         acc_store = modest_runtime_get_account_store ();
1791
1792         /* Create the info for the connect and perform */
1793         info = g_slice_new (SendReceiveInfo);
1794         info->account_name = acc_name;
1795         info->win = (win) ? g_object_ref (win) : NULL;
1796         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1797                                                                      TNY_ACCOUNT_TYPE_STORE);
1798
1799         /* Invoke the connect and perform */
1800         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
1801                                              force_connection, info->account, 
1802                                              do_send_receive_performer, info);
1803 }
1804
1805
1806 static void
1807 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1808                                   ModestWindow *win)
1809 {
1810         TnyTransportAccount *transport_account;
1811         TnySendQueue *send_queue = NULL;
1812         GError *error = NULL;
1813
1814         /* Get transport account */
1815         transport_account =
1816                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1817                                       (modest_runtime_get_account_store(),
1818                                        account_name,
1819                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1820         if (!transport_account) {
1821                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1822                 goto frees;
1823         }
1824
1825         /* Get send queue*/
1826         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1827         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1828                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1829                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1830                              "modest: could not find send queue for account\n");
1831         } else {
1832                 /* Keeep messages in outbox folder */
1833                 tny_send_queue_cancel (send_queue, FALSE, &error);
1834         }       
1835
1836  frees:
1837         if (transport_account != NULL) 
1838                 g_object_unref (G_OBJECT (transport_account));
1839 }
1840
1841 static void
1842 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1843 {
1844         GSList *account_names, *iter;
1845
1846         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1847                                                           TRUE);
1848
1849         iter = account_names;
1850         while (iter) {                  
1851                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1852                 iter = g_slist_next (iter);
1853         }
1854
1855         modest_account_mgr_free_account_names (account_names);
1856         account_names = NULL;
1857 }
1858
1859 void
1860 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1861
1862 {
1863         /* Check if accounts exist */
1864         gboolean accounts_exist = 
1865                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1866         
1867         /* If not, allow the user to create an account before trying to send/receive. */
1868         if (!accounts_exist)
1869                 modest_ui_actions_on_accounts (NULL, win);
1870         
1871         /* Cancel all sending operaitons */     
1872         modest_ui_actions_cancel_send_all (win);
1873 }
1874
1875 /*
1876  * Refreshes all accounts. This function will be used by automatic
1877  * updates
1878  */
1879 void
1880 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
1881                                        gboolean force_connection)
1882 {
1883         GSList *account_names, *iter;
1884
1885         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1886                                                           TRUE);
1887
1888         iter = account_names;
1889         while (iter) {                  
1890                 modest_ui_actions_do_send_receive ((const char*) iter->data, force_connection, win);
1891                 iter = g_slist_next (iter);
1892         }
1893
1894         modest_account_mgr_free_account_names (account_names);
1895         account_names = NULL;
1896 }
1897
1898 /*
1899  * Handler of the click on Send&Receive button in the main toolbar
1900  */
1901 void
1902 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1903 {
1904         /* Check if accounts exist */
1905         gboolean accounts_exist;
1906
1907         accounts_exist =
1908                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1909         
1910         /* If not, allow the user to create an account before trying to send/receive. */
1911         if (!accounts_exist)
1912                 modest_ui_actions_on_accounts (NULL, win);
1913         
1914         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1915         if (MODEST_IS_MAIN_WINDOW (win)) {
1916                 GtkWidget *folder_view;
1917                 TnyFolderStore *folder_store;
1918
1919                 folder_view = 
1920                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1921                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1922                 if (!folder_view)
1923                         return;
1924                 
1925                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1926         
1927                 if (folder_store)
1928                         g_object_unref (folder_store);
1929         }       
1930         
1931         /* Refresh the active account. Force the connection if needed */
1932         modest_ui_actions_do_send_receive (NULL, TRUE, win);
1933 }
1934
1935
1936 void
1937 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1938 {
1939         ModestConf *conf;
1940         GtkWidget *header_view;
1941         
1942         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1943
1944         header_view = modest_main_window_get_child_widget (main_window,
1945                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1946         if (!header_view)
1947                 return;
1948
1949         conf = modest_runtime_get_conf ();
1950         
1951         /* what is saved/restored is depending on the style; thus; we save with
1952          * old style, then update the style, and restore for this new style
1953          */
1954         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1955         
1956         if (modest_header_view_get_style
1957             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1958                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1959                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1960         else
1961                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1962                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1963
1964         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1965                                       MODEST_CONF_HEADER_VIEW_KEY);
1966 }
1967
1968
1969 void 
1970 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1971                                       TnyHeader *header,
1972                                       ModestMainWindow *main_window)
1973 {
1974         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1975         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1976         
1977         /* in the case the folder is empty, show the empty folder message and focus
1978          * folder view */
1979         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1980                 if (modest_header_view_is_empty (header_view)) {
1981                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1982                         GtkWidget *folder_view = 
1983                                 modest_main_window_get_child_widget (main_window,
1984                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1985                         if (folder != NULL) 
1986                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1987                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1988                         return;
1989                 }
1990         }
1991         /* If no header has been selected then exit */
1992         if (!header)
1993                 return;
1994
1995         /* Update focus */
1996         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1997             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1998
1999         /* Update toolbar dimming state */
2000         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2001 }
2002
2003 void
2004 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2005                                        TnyHeader *header,
2006                                        ModestMainWindow *main_window)
2007 {
2008         TnyList *headers;
2009
2010         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2011
2012         if (!header)
2013                 return;
2014
2015         if (modest_header_view_count_selected_headers (header_view) > 1) {
2016                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2017                 return;
2018         }
2019
2020
2021 /*      headers = tny_simple_list_new (); */
2022 /*      tny_list_prepend (headers, G_OBJECT (header)); */
2023         headers = modest_header_view_get_selected_headers (header_view);
2024
2025         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2026
2027         g_object_unref (headers);
2028 }
2029
2030 static void
2031 set_active_account_from_tny_account (TnyAccount *account,
2032                                      ModestWindow *window)
2033 {
2034         const gchar *server_acc_name = tny_account_get_id (account);
2035         
2036         /* We need the TnyAccount provided by the
2037            account store because that is the one that
2038            knows the name of the Modest account */
2039         TnyAccount *modest_server_account = modest_server_account = 
2040                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2041                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2042                                                              server_acc_name);
2043         if (!modest_server_account) {
2044                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2045                 return;
2046         }
2047
2048         /* Update active account, but only if it's not a pseudo-account */
2049         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2050             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2051                 const gchar *modest_acc_name = 
2052                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2053                 if (modest_acc_name)
2054                         modest_window_set_active_account (window, modest_acc_name);
2055         }
2056         
2057         g_object_unref (modest_server_account);
2058 }
2059
2060
2061 static void
2062 folder_refreshed_cb (ModestMailOperation *mail_op, 
2063                      TnyFolder *folder, 
2064                      gpointer user_data)
2065 {
2066         ModestMainWindow *win = NULL;
2067         GtkWidget *header_view;
2068
2069         g_return_if_fail (TNY_IS_FOLDER (folder));
2070
2071         win = MODEST_MAIN_WINDOW (user_data);
2072         header_view = 
2073                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2074
2075         if (header_view) {
2076                 TnyFolder *current_folder;
2077
2078                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2079                 if (current_folder != NULL && folder != current_folder) {
2080                         g_object_unref (current_folder);
2081                         return;
2082                 } else if (current_folder)
2083                         g_object_unref (current_folder);
2084         }
2085
2086         /* Check if folder is empty and set headers view contents style */
2087         if (tny_folder_get_all_count (folder) == 0)
2088                 modest_main_window_set_contents_style (win,
2089                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2090 }
2091
2092 void 
2093 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2094                                                TnyFolderStore *folder_store, 
2095                                                gboolean selected,
2096                                                ModestMainWindow *main_window)
2097 {
2098         ModestConf *conf;
2099         GtkWidget *header_view;
2100
2101         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2102
2103         header_view = modest_main_window_get_child_widget(main_window,
2104                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2105         if (!header_view)
2106                 return;
2107         
2108         conf = modest_runtime_get_conf ();
2109
2110         if (TNY_IS_ACCOUNT (folder_store)) {
2111                 if (selected) {
2112                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2113                         
2114                         /* Show account details */
2115                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2116                 }
2117         } else {
2118                 if (TNY_IS_FOLDER (folder_store) && selected) {
2119                         
2120                         /* Update the active account */
2121                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2122                         if (account) {
2123                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2124                                 g_object_unref (account);
2125                                 account = NULL;
2126                         }
2127
2128                         /* Set the header style by default, it could
2129                            be changed later by the refresh callback to
2130                            empty */
2131                         modest_main_window_set_contents_style (main_window, 
2132                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2133
2134                         /* Set folder on header view. This function
2135                            will call tny_folder_refresh_async so we
2136                            pass a callback that will be called when
2137                            finished. We use that callback to set the
2138                            empty view if there are no messages */
2139                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2140                                                        TNY_FOLDER (folder_store),
2141                                                        folder_refreshed_cb,
2142                                                        main_window);
2143                         
2144                         /* Restore configuration. We need to do this
2145                            *after* the set_folder because the widget
2146                            memory asks the header view about its
2147                            folder  */
2148                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2149                                                       G_OBJECT(header_view),
2150                                                       MODEST_CONF_HEADER_VIEW_KEY);
2151                 } else {
2152                         /* Update the active account */
2153                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2154                         /* Save only if we're seeing headers */
2155                         if (modest_main_window_get_contents_style (main_window) ==
2156                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2157                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2158                                                            MODEST_CONF_HEADER_VIEW_KEY);
2159                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2160                 }
2161         }
2162
2163         /* Update toolbar dimming state */
2164         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2165 }
2166
2167 void 
2168 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2169                                      ModestWindow *win)
2170 {
2171         GtkWidget *dialog;
2172         gchar *txt, *item;
2173         gboolean online;
2174
2175         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2176         
2177         online = tny_device_is_online (modest_runtime_get_device());
2178
2179         if (online) {
2180                 /* already online -- the item is simply not there... */
2181                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2182                                                  GTK_DIALOG_MODAL,
2183                                                  GTK_MESSAGE_WARNING,
2184                                                  GTK_BUTTONS_NONE,
2185                                                  _("The %s you selected cannot be found"),
2186                                                  item);
2187                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2188                 gtk_dialog_run (GTK_DIALOG(dialog));
2189         } else {
2190                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2191                                                       GTK_WINDOW (win),
2192                                                       GTK_DIALOG_MODAL,
2193                                                       _("mcen_bd_dialog_cancel"),
2194                                                       GTK_RESPONSE_REJECT,
2195                                                       _("mcen_bd_dialog_ok"),
2196                                                       GTK_RESPONSE_ACCEPT,
2197                                                       NULL);
2198                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2199                                          "Do you want to get online?"), item);
2200                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2201                                     gtk_label_new (txt), FALSE, FALSE, 0);
2202                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2203                 g_free (txt);
2204
2205                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2206                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2207                         /* TODO: Comment about why is this commented out: */
2208                         /* modest_platform_connect_and_wait (); */
2209                 }
2210         }
2211         gtk_widget_destroy (dialog);
2212 }
2213
2214 void
2215 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2216                                      ModestWindow *win)
2217 {
2218         /* g_message ("%s %s", __FUNCTION__, link); */
2219 }       
2220
2221
2222 void
2223 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2224                                         ModestWindow *win)
2225 {
2226         modest_platform_activate_uri (link);
2227 }
2228
2229 void
2230 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2231                                           ModestWindow *win)
2232 {
2233         modest_platform_show_uri_popup (link);
2234 }
2235
2236 void
2237 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2238                                              ModestWindow *win)
2239 {
2240         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2241 }
2242
2243 void
2244 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2245                                           const gchar *address,
2246                                           ModestWindow *win)
2247 {
2248         /* g_message ("%s %s", __FUNCTION__, address); */
2249 }
2250
2251 static void
2252 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2253                       TnyMsg *saved_draft,
2254                       gpointer user_data)
2255 {
2256         ModestMsgEditWindow *edit_window;
2257         ModestMainWindow *win;
2258
2259         /* FIXME. Make the header view sensitive again. This is a
2260          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2261          * for details */
2262         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2263                                          modest_runtime_get_window_mgr(), FALSE));
2264         if (win != NULL) {
2265                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2266                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2267                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2268         }
2269
2270         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2271
2272         /* It might not be a good idea to do nothing if there was an error,
2273          * so let's at least show a generic error banner. */
2274         /* TODO error while saving attachment, show "Saving draft failed" banner */
2275         if (modest_mail_operation_get_error (mail_op) != NULL) {
2276                 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_op))->message);
2277                 modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
2278         } else {
2279                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2280         }
2281         g_object_unref(edit_window);
2282 }
2283
2284 void
2285 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2286 {
2287         TnyTransportAccount *transport_account;
2288         ModestMailOperation *mail_operation;
2289         MsgData *data;
2290         gchar *account_name, *from;
2291         ModestAccountMgr *account_mgr;
2292         char *info_text;
2293
2294         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2295         
2296         data = modest_msg_edit_window_get_msg_data (edit_window);
2297
2298         account_name = g_strdup (data->account_name);
2299         account_mgr = modest_runtime_get_account_mgr();
2300         if (!account_name)
2301                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2302         if (!account_name) 
2303                 account_name = modest_account_mgr_get_default_account (account_mgr);
2304         if (!account_name) {
2305                 g_printerr ("modest: no account found\n");
2306                 modest_msg_edit_window_free_msg_data (edit_window, data);
2307                 return;
2308         }
2309
2310         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2311                 account_name = g_strdup (data->account_name);
2312         }
2313
2314         transport_account =
2315                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2316                                       (modest_runtime_get_account_store(),
2317                                        account_name,
2318                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2319         if (!transport_account) {
2320                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2321                 g_free (account_name);
2322                 modest_msg_edit_window_free_msg_data (edit_window, data);
2323                 return;
2324         }
2325         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2326
2327         /* Create the mail operation */         
2328         mail_operation = modest_mail_operation_new (NULL);
2329         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2330
2331         modest_mail_operation_save_to_drafts (mail_operation,
2332                                               transport_account,
2333                                               data->draft_msg,
2334                                               from,
2335                                               data->to, 
2336                                               data->cc, 
2337                                               data->bcc,
2338                                               data->subject, 
2339                                               data->plain_body, 
2340                                               data->html_body,
2341                                               data->attachments,
2342                                               data->images,
2343                                               data->priority_flags,
2344                                               on_save_to_drafts_cb,
2345                                               g_object_ref(edit_window));
2346         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2347         modest_platform_information_banner (NULL, NULL, info_text);
2348
2349         /* Frees */
2350         g_free (info_text);
2351         g_free (from);
2352         g_free (account_name);
2353         g_object_unref (G_OBJECT (transport_account));
2354         g_object_unref (G_OBJECT (mail_operation));
2355
2356         modest_msg_edit_window_free_msg_data (edit_window, data);
2357         modest_msg_edit_window_reset_modified (edit_window);
2358
2359         /* ** FIXME **
2360          * If the drafts folder is selected then make the header view
2361          * insensitive while the message is being saved to drafts
2362          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2363          * is not very clean but it avoids letting the drafts folder
2364          * in an inconsistent state: the user could edit the message
2365          * being saved and undesirable things would happen.
2366          * In the average case the user won't notice anything at
2367          * all. In the worst case (the user is editing a really big
2368          * file from Drafts) the header view will be insensitive
2369          * during the saving process (10 or 20 seconds, depending on
2370          * the message). Anyway this is just a quick workaround: once
2371          * we find a better solution it should be removed
2372          * See NB#65125 (commend #18) for details.
2373          */
2374         ModestMainWindow *win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2375                 modest_runtime_get_window_mgr(), FALSE));
2376         if (win != NULL) {
2377                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2378                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2379                 if (view != NULL) {
2380                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2381                         if (folder) {
2382                                 if (modest_tny_folder_is_local_folder(folder)) {
2383                                         TnyFolderType folder_type;
2384                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2385                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2386                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2387                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2388                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2389                                         }
2390                                 }
2391                         }
2392                         if (folder != NULL) g_object_unref(folder);
2393                 }
2394         }
2395 }
2396
2397 /* For instance, when clicking the Send toolbar button when editing a message: */
2398 void
2399 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2400 {
2401         TnyTransportAccount *transport_account = NULL;
2402
2403         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2404
2405         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2406                 return;
2407         
2408         /* FIXME: Code added just for testing. The final version will
2409            use the send queue provided by tinymail and some
2410            classifier */
2411         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2412
2413         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2414         gchar *account_name = g_strdup (data->account_name);
2415         if (!account_name)
2416                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2417
2418         if (!account_name) 
2419                 account_name = modest_account_mgr_get_default_account (account_mgr);
2420                 
2421         if (!account_name) {
2422                 modest_msg_edit_window_free_msg_data (edit_window, data);
2423                 /* Run account setup wizard */
2424                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2425                         return;
2426                 }
2427         }
2428         
2429         /* Get the currently-active transport account for this modest account: */
2430         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2431                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2432                                                           (modest_runtime_get_account_store(),
2433                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2434         }
2435         
2436         if (!transport_account) {
2437                 modest_msg_edit_window_free_msg_data (edit_window, data);
2438                 /* Run account setup wizard */
2439                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2440                         return;
2441         }
2442         
2443         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2444
2445         /* Create the mail operation */
2446         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2447         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2448
2449         modest_mail_operation_send_new_mail (mail_operation,
2450                                              transport_account,
2451                                              data->draft_msg,
2452                                              from,
2453                                              data->to, 
2454                                              data->cc, 
2455                                              data->bcc,
2456                                              data->subject, 
2457                                              data->plain_body, 
2458                                              data->html_body,
2459                                              data->attachments,
2460                                              data->images,
2461                                              data->priority_flags);
2462
2463         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2464                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2465
2466                                              
2467         /* Free data: */
2468         g_free (from);
2469         g_free (account_name);
2470         g_object_unref (G_OBJECT (transport_account));
2471         g_object_unref (G_OBJECT (mail_operation));
2472
2473         modest_msg_edit_window_free_msg_data (edit_window, data);
2474         modest_msg_edit_window_set_sent (edit_window, TRUE);
2475
2476         /* Save settings and close the window: */
2477         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2478 }
2479
2480 void 
2481 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2482                                   ModestMsgEditWindow *window)
2483 {
2484         ModestMsgEditFormatState *format_state = NULL;
2485
2486         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2487         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2488
2489         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2490                 return;
2491
2492         format_state = modest_msg_edit_window_get_format_state (window);
2493         g_return_if_fail (format_state != NULL);
2494
2495         format_state->bold = gtk_toggle_action_get_active (action);
2496         modest_msg_edit_window_set_format_state (window, format_state);
2497         g_free (format_state);
2498         
2499 }
2500
2501 void 
2502 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2503                                      ModestMsgEditWindow *window)
2504 {
2505         ModestMsgEditFormatState *format_state = NULL;
2506
2507         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2508         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2509
2510         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2511                 return;
2512
2513         format_state = modest_msg_edit_window_get_format_state (window);
2514         g_return_if_fail (format_state != NULL);
2515
2516         format_state->italics = gtk_toggle_action_get_active (action);
2517         modest_msg_edit_window_set_format_state (window, format_state);
2518         g_free (format_state);
2519         
2520 }
2521
2522 void 
2523 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2524                                      ModestMsgEditWindow *window)
2525 {
2526         ModestMsgEditFormatState *format_state = NULL;
2527
2528         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2529         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2530
2531         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2532                 return;
2533
2534         format_state = modest_msg_edit_window_get_format_state (window);
2535         g_return_if_fail (format_state != NULL);
2536
2537         format_state->bullet = gtk_toggle_action_get_active (action);
2538         modest_msg_edit_window_set_format_state (window, format_state);
2539         g_free (format_state);
2540         
2541 }
2542
2543 void 
2544 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2545                                      GtkRadioAction *selected,
2546                                      ModestMsgEditWindow *window)
2547 {
2548         ModestMsgEditFormatState *format_state = NULL;
2549         GtkJustification value;
2550
2551         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2552
2553         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2554                 return;
2555
2556         value = gtk_radio_action_get_current_value (selected);
2557
2558         format_state = modest_msg_edit_window_get_format_state (window);
2559         g_return_if_fail (format_state != NULL);
2560
2561         format_state->justification = value;
2562         modest_msg_edit_window_set_format_state (window, format_state);
2563         g_free (format_state);
2564 }
2565
2566 void 
2567 modest_ui_actions_on_select_editor_color (GtkAction *action,
2568                                           ModestMsgEditWindow *window)
2569 {
2570         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2571         g_return_if_fail (GTK_IS_ACTION (action));
2572
2573         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2574                 return;
2575
2576         modest_msg_edit_window_select_color (window);
2577 }
2578
2579 void 
2580 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2581                                                      ModestMsgEditWindow *window)
2582 {
2583         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2584         g_return_if_fail (GTK_IS_ACTION (action));
2585
2586         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2587                 return;
2588
2589         modest_msg_edit_window_select_background_color (window);
2590 }
2591
2592 void 
2593 modest_ui_actions_on_insert_image (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         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2600                 return;
2601
2602         modest_msg_edit_window_insert_image (window);
2603 }
2604
2605 void 
2606 modest_ui_actions_on_attach_file (GtkAction *action,
2607                                   ModestMsgEditWindow *window)
2608 {
2609         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2610         g_return_if_fail (GTK_IS_ACTION (action));
2611
2612         modest_msg_edit_window_offer_attach_file (window);
2613 }
2614
2615 void 
2616 modest_ui_actions_on_remove_attachments (GtkAction *action,
2617                                          ModestMsgEditWindow *window)
2618 {
2619         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2620         g_return_if_fail (GTK_IS_ACTION (action));
2621
2622         modest_msg_edit_window_remove_attachments (window, NULL);
2623 }
2624
2625 static void
2626 do_create_folder_cb (ModestMailOperation *mail_op,
2627                      TnyFolderStore *parent_folder, 
2628                      TnyFolder *new_folder,
2629                      gpointer user_data)
2630 {
2631         gchar *suggested_name = (gchar *) user_data;
2632         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2633
2634         if (modest_mail_operation_get_error (mail_op)) {
2635                 /* Show an error */
2636                 modest_platform_information_banner (GTK_WIDGET (source_win), NULL,
2637                                                     _("mail_in_ui_folder_create_error"));
2638
2639                 /* Try again */
2640                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2641         } else {
2642                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2643                  * FIXME: any other? */         
2644                 GtkWidget *folder_view;
2645
2646                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2647                         folder_view = 
2648                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2649                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2650                 else
2651                         folder_view =
2652                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2653                 
2654                 /* Select the newly created folder */
2655                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2656                                                   new_folder, FALSE);
2657                 g_object_unref (new_folder);
2658         }
2659         /* Free. Note that the first time it'll be NULL so noop */
2660         g_free (suggested_name);
2661         g_object_unref (source_win);
2662 }
2663
2664 static void
2665 do_create_folder (GtkWindow *parent_window, 
2666                   TnyFolderStore *parent_folder, 
2667                   const gchar *suggested_name)
2668 {
2669         gint result;
2670         gchar *folder_name = NULL;
2671
2672         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2673                                                         parent_folder,
2674                                                         (gchar *) suggested_name,
2675                                                         &folder_name);
2676         
2677         if (result == GTK_RESPONSE_ACCEPT) {
2678                 ModestMailOperation *mail_op;
2679                 
2680                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2681                         
2682                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2683                                                  mail_op);
2684                 modest_mail_operation_create_folder (mail_op,
2685                                                      parent_folder,
2686                                                      (const gchar *) folder_name,
2687                                                      do_create_folder_cb,
2688                                                      folder_name);
2689                 g_object_unref (mail_op);
2690         }
2691 }
2692
2693 static void
2694 create_folder_performer (gboolean canceled, 
2695                          GError *err,
2696                          GtkWindow *parent_window, 
2697                          TnyAccount *account, 
2698                          gpointer user_data)
2699 {
2700         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2701
2702         if (canceled || err) {
2703                 goto frees;
2704         }
2705
2706         /* Run the new folder dialog */
2707         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2708
2709  frees:
2710         g_object_unref (parent_folder);
2711 }
2712
2713 static void
2714 modest_ui_actions_create_folder(GtkWidget *parent_window,
2715                                 GtkWidget *folder_view)
2716 {
2717         TnyFolderStore *parent_folder;
2718
2719         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2720         
2721         if (parent_folder) {
2722                 /* The parent folder will be freed in the callback */
2723                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2724                                                                TRUE,
2725                                                                parent_folder,
2726                                                                create_folder_performer, 
2727                                                                parent_folder);
2728         }
2729 }
2730
2731 void 
2732 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2733 {
2734         GtkWidget *folder_view;
2735         
2736         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2737
2738         folder_view = modest_main_window_get_child_widget (main_window,
2739                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2740         if (!folder_view)
2741                 return;
2742
2743         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2744 }
2745
2746 static void
2747 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2748                                                gpointer user_data)
2749 {
2750         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2751         const GError *error = NULL;
2752         const gchar *message = NULL;
2753         
2754         /* Get error message */
2755         error = modest_mail_operation_get_error (mail_op);
2756         if (!error)
2757                 g_return_if_reached ();
2758
2759         switch (error->code) {
2760         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2761                 message = _CS("ckdg_ib_folder_already_exists");
2762                 break;
2763         default:
2764                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2765                            error->code, error->message);
2766                 return;
2767         }
2768
2769         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2770 }
2771
2772 typedef struct {
2773         TnyFolderStore *folder;
2774         gchar *new_name;
2775 } RenameFolderInfo;
2776
2777 static void
2778 on_rename_folder_cb (ModestMailOperation *mail_op, 
2779                      TnyFolder *new_folder,
2780                      gpointer user_data)
2781 {
2782         /* Select now */
2783         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2784                                           new_folder, FALSE);
2785 }
2786
2787 static void
2788 on_rename_folder_performer (gboolean canceled, 
2789                             GError *err, 
2790                             GtkWindow *parent_window, 
2791                             TnyAccount *account, 
2792                             gpointer user_data)
2793 {
2794         ModestMailOperation *mail_op = NULL;
2795         GtkTreeSelection *sel = NULL;
2796         GtkWidget *folder_view = NULL;
2797         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2798
2799         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2800
2801                 folder_view = modest_main_window_get_child_widget (
2802                                 MODEST_MAIN_WINDOW (parent_window),
2803                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2804
2805                 mail_op = 
2806                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2807                                         modest_ui_actions_rename_folder_error_handler,
2808                                         parent_window, NULL);
2809
2810                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2811                                 mail_op);
2812
2813                 /* Clear the headers view */
2814                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2815                 gtk_tree_selection_unselect_all (sel);
2816
2817                 /* Actually rename the folder */
2818                 modest_mail_operation_rename_folder (mail_op,
2819                                                      TNY_FOLDER (data->folder),
2820                                                      (const gchar *) (data->new_name),
2821                                                      on_rename_folder_cb,
2822                                                      folder_view);
2823         }
2824
2825         g_object_unref (mail_op);
2826         g_free (data->new_name);
2827         g_free (data);
2828 }
2829
2830 void 
2831 modest_ui_actions_on_rename_folder (GtkAction *action,
2832                                      ModestMainWindow *main_window)
2833 {
2834         TnyFolderStore *folder;
2835         GtkWidget *folder_view;
2836         GtkWidget *header_view; 
2837
2838         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2839
2840         folder_view = modest_main_window_get_child_widget (main_window,
2841                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2842         if (!folder_view)
2843                 return;
2844
2845         header_view = modest_main_window_get_child_widget (main_window,
2846                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2847         
2848         if (!header_view)
2849                 return;
2850
2851         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2852
2853         if (!folder)
2854                 return;
2855
2856         if (TNY_IS_FOLDER (folder)) {
2857                 gchar *folder_name;
2858                 gint response;
2859                 const gchar *current_name;
2860                 TnyFolderStore *parent;
2861                 gboolean do_rename = TRUE;
2862
2863                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2864                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2865                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2866                                                                      parent, current_name, 
2867                                                                      &folder_name);
2868                 g_object_unref (parent);
2869
2870                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2871                         do_rename = FALSE;
2872                 } else {
2873                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2874                         rename_folder_data->folder = folder;
2875                         rename_folder_data->new_name = folder_name;
2876                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
2877                                         folder, on_rename_folder_performer, rename_folder_data);
2878                 }
2879         }
2880         g_object_unref (folder);
2881 }
2882
2883 static void
2884 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2885                                                gpointer user_data)
2886 {
2887         GObject *win = modest_mail_operation_get_source (mail_op);
2888
2889         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2890                                                 _("mail_in_ui_folder_delete_error"));
2891         g_object_unref (win);
2892 }
2893
2894 typedef struct {
2895         TnyFolderStore *folder;
2896         gboolean move_to_trash;
2897 } DeleteFolderInfo;
2898
2899 static void
2900 on_delete_folder_cb (gboolean canceled, 
2901                   GError *err,
2902                   GtkWindow *parent_window, 
2903                   TnyAccount *account, 
2904                   gpointer user_data)
2905 {
2906         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
2907         GtkWidget *folder_view;
2908         ModestMailOperation *mail_op;
2909         GtkTreeSelection *sel;
2910         
2911         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
2912                 g_object_unref (G_OBJECT (info->folder));
2913                 g_free (info);
2914         }
2915         
2916         folder_view = modest_main_window_get_child_widget (
2917                         MODEST_MAIN_WINDOW (parent_window),
2918                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2919
2920         /* Unselect the folder before deleting it to free the headers */
2921         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2922         gtk_tree_selection_unselect_all (sel);
2923
2924         /* Create the mail operation */
2925         mail_op =
2926                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2927                                 modest_ui_actions_delete_folder_error_handler,
2928                                 NULL, NULL);
2929
2930         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2931                         mail_op);
2932         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
2933         
2934         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2935
2936         g_object_unref (G_OBJECT (mail_op));
2937         g_object_unref (G_OBJECT (info->folder));
2938         g_free (info);
2939 }
2940
2941 static void
2942 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2943 {
2944         TnyFolderStore *folder;
2945         GtkWidget *folder_view;
2946         gint response;
2947         gchar *message;
2948         
2949         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2950
2951         folder_view = modest_main_window_get_child_widget (main_window,
2952                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2953         if (!folder_view)
2954                 return;
2955
2956         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2957
2958         /* Show an error if it's an account */
2959         if (!TNY_IS_FOLDER (folder)) {
2960                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2961                                                         _("mail_in_ui_folder_delete_error"));
2962                 g_object_unref (G_OBJECT (folder));
2963                 return;
2964         }
2965
2966         /* Ask the user */      
2967         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2968                                     tny_folder_get_name (TNY_FOLDER (folder)));
2969         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2970                                                             (const gchar *) message);
2971         g_free (message);
2972
2973         if (response == GTK_RESPONSE_OK) {
2974                 DeleteFolderInfo *info;
2975                 info = g_new0(DeleteFolderInfo, 1);
2976                 info->folder = folder;
2977                 info->move_to_trash = move_to_trash;
2978                 g_object_ref (G_OBJECT (info->folder));
2979                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
2980                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
2981                                                                TRUE,
2982                                                                TNY_FOLDER_STORE (account), 
2983                                                                on_delete_folder_cb, info);
2984                 g_object_unref (account);
2985         }
2986         g_object_unref (G_OBJECT (folder));
2987 }
2988
2989 void 
2990 modest_ui_actions_on_delete_folder (GtkAction *action,
2991                                      ModestMainWindow *main_window)
2992 {
2993         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2994         
2995         delete_folder (main_window, FALSE);
2996 }
2997
2998 void 
2999 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3000 {
3001         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3002         
3003         delete_folder (main_window, TRUE);
3004 }
3005
3006
3007 static void
3008 show_error (GtkWidget *parent_widget, const gchar* text)
3009 {
3010         modest_platform_information_banner(parent_widget, NULL, text);
3011         
3012 #if 0
3013         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
3014         /*
3015           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
3016           (GtkDialogFlags)0,
3017           GTK_MESSAGE_ERROR,
3018           GTK_BUTTONS_OK,
3019           text ));
3020         */
3021                  
3022         gtk_dialog_run (dialog);
3023         gtk_widget_destroy (GTK_WIDGET (dialog));
3024 #endif
3025 }
3026
3027 void
3028 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3029                                          const gchar* server_account_name,
3030                                          gchar **username,
3031                                          gchar **password, 
3032                                          gboolean *cancel, 
3033                                          gboolean *remember,
3034                                          ModestMainWindow *main_window)
3035 {
3036         g_return_if_fail(server_account_name);
3037         
3038         /* Initalize output parameters: */
3039         if (cancel)
3040                 *cancel = FALSE;
3041                 
3042         if (remember)
3043                 *remember = TRUE;
3044                 
3045 #ifdef MODEST_PLATFORM_MAEMO
3046         /* Maemo uses a different (awkward) button order,
3047          * It should probably just use gtk_alternative_dialog_button_order ().
3048          */
3049         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3050                                               NULL,
3051                                               GTK_DIALOG_MODAL,
3052                                               _("mcen_bd_dialog_ok"),
3053                                               GTK_RESPONSE_ACCEPT,
3054                                               _("mcen_bd_dialog_cancel"),
3055                                               GTK_RESPONSE_REJECT,
3056                                               NULL);
3057 #else
3058         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3059                                               NULL,
3060                                               GTK_DIALOG_MODAL,
3061                                               GTK_STOCK_CANCEL,
3062                                               GTK_RESPONSE_REJECT,
3063                                               GTK_STOCK_OK,
3064                                               GTK_RESPONSE_ACCEPT,
3065                                               NULL);
3066 #endif /* MODEST_PLATFORM_MAEMO */
3067
3068         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3069         
3070         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3071                 modest_runtime_get_account_mgr(), server_account_name);
3072         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3073                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3074                 if (cancel)
3075                         *cancel = TRUE;
3076                 return;
3077         }
3078         
3079         /* This causes a warning because the logical ID has no %s in it, 
3080          * though the translation does, but there is not much we can do about that: */
3081         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3082         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3083                             FALSE, FALSE, 0);
3084         g_free (txt);
3085         g_free (server_name);
3086         server_name = NULL;
3087
3088         /* username: */
3089         gchar *initial_username = modest_account_mgr_get_server_account_username (
3090                 modest_runtime_get_account_mgr(), server_account_name);
3091         
3092         GtkWidget *entry_username = gtk_entry_new ();
3093         if (initial_username)
3094                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3095         /* Dim this if a connection has ever succeeded with this username,
3096          * as per the UI spec: */
3097         const gboolean username_known = 
3098                 modest_account_mgr_get_server_account_username_has_succeeded(
3099                         modest_runtime_get_account_mgr(), server_account_name);
3100         gtk_widget_set_sensitive (entry_username, !username_known);
3101         
3102 #ifdef MODEST_PLATFORM_MAEMO
3103         /* Auto-capitalization is the default, so let's turn it off: */
3104         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3105         
3106         /* Create a size group to be used by all captions.
3107          * Note that HildonCaption does not create a default size group if we do not specify one.
3108          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3109         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3110         
3111         GtkWidget *caption = hildon_caption_new (sizegroup, 
3112                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3113         gtk_widget_show (entry_username);
3114         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3115                 FALSE, FALSE, MODEST_MARGIN_HALF);
3116         gtk_widget_show (caption);
3117 #else 
3118         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3119                             TRUE, FALSE, 0);
3120 #endif /* MODEST_PLATFORM_MAEMO */      
3121                             
3122         /* password: */
3123         GtkWidget *entry_password = gtk_entry_new ();
3124         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3125         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3126         
3127 #ifdef MODEST_PLATFORM_MAEMO
3128         /* Auto-capitalization is the default, so let's turn it off: */
3129         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3130                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3131         
3132         caption = hildon_caption_new (sizegroup, 
3133                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3134         gtk_widget_show (entry_password);
3135         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3136                 FALSE, FALSE, MODEST_MARGIN_HALF);
3137         gtk_widget_show (caption);
3138         g_object_unref (sizegroup);
3139 #else 
3140         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3141                             TRUE, FALSE, 0);
3142 #endif /* MODEST_PLATFORM_MAEMO */      
3143
3144         if (initial_username != NULL)
3145                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3146                                 
3147 /* This is not in the Maemo UI spec:
3148         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3149         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3150                             TRUE, FALSE, 0);
3151 */
3152
3153         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3154         
3155         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3156                 if (username) {
3157                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3158                         
3159                         modest_account_mgr_set_server_account_username (
3160                                  modest_runtime_get_account_mgr(), server_account_name, 
3161                                  *username);
3162                                  
3163                         const gboolean username_was_changed = 
3164                                 (strcmp (*username, initial_username) != 0);
3165                         if (username_was_changed) {
3166                                 g_warning ("%s: tinymail does not yet support changing the "
3167                                         "username in the get_password() callback.\n", __FUNCTION__);
3168                         }
3169                 }
3170                         
3171                 if (password) {
3172                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3173                         
3174                         /* We do not save the password in the configuration, 
3175                          * because this function is only called for passwords that should 
3176                          * not be remembered:
3177                         modest_server_account_set_password (
3178                                  modest_runtime_get_account_mgr(), server_account_name, 
3179                                  *password);
3180                         */
3181                 }
3182                 
3183                 if (cancel)
3184                         *cancel   = FALSE;
3185                         
3186         } else {
3187                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3188                 
3189                 if (username)
3190                         *username = NULL;
3191                         
3192                 if (password)
3193                         *password = NULL;
3194                         
3195                 if (cancel)
3196                         *cancel   = TRUE;
3197         }
3198
3199 /* This is not in the Maemo UI spec:
3200         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3201                 *remember = TRUE;
3202         else
3203                 *remember = FALSE;
3204 */
3205
3206         gtk_widget_destroy (dialog);
3207         
3208         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3209 }
3210
3211 void
3212 modest_ui_actions_on_cut (GtkAction *action,
3213                           ModestWindow *window)
3214 {
3215         GtkWidget *focused_widget;
3216         GtkClipboard *clipboard;
3217
3218         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3219         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3220         if (GTK_IS_EDITABLE (focused_widget)) {
3221                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3222                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3223                 gtk_clipboard_store (clipboard);
3224         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3225                 GtkTextBuffer *buffer;
3226
3227                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3228                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3229                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3230                 gtk_clipboard_store (clipboard);
3231         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3232                 TnyList *header_list = modest_header_view_get_selected_headers (
3233                                 MODEST_HEADER_VIEW (focused_widget));
3234                 gboolean continue_download = FALSE;
3235                 gint num_of_unc_msgs;
3236
3237                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3238
3239                 if (num_of_unc_msgs) {
3240                         TnyAccount *account = get_account_from_header_list (header_list);
3241                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3242                         g_object_unref (account);
3243                 }
3244
3245                 if (num_of_unc_msgs == 0 || continue_download) {
3246 /*                      modest_platform_information_banner (
3247                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3248                         modest_header_view_cut_selection (
3249                                         MODEST_HEADER_VIEW (focused_widget));
3250                 }
3251
3252                 g_object_unref (header_list);
3253         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3254                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3255         }
3256 }
3257
3258 void
3259 modest_ui_actions_on_copy (GtkAction *action,
3260                            ModestWindow *window)
3261 {
3262         GtkClipboard *clipboard;
3263         GtkWidget *focused_widget;
3264         gboolean copied = TRUE;
3265
3266         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3267         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3268
3269         if (GTK_IS_LABEL (focused_widget)) {
3270                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3271                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3272                 gtk_clipboard_store (clipboard);
3273         } else if (GTK_IS_EDITABLE (focused_widget)) {
3274                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3275                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3276                 gtk_clipboard_store (clipboard);
3277         } else if (GTK_IS_HTML (focused_widget)) {
3278                 gtk_html_copy (GTK_HTML (focused_widget));
3279                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3280                 gtk_clipboard_store (clipboard);
3281         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3282                 GtkTextBuffer *buffer;
3283                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3284                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3285                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3286                 gtk_clipboard_store (clipboard);
3287         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3288                 TnyList *header_list = modest_header_view_get_selected_headers (
3289                                 MODEST_HEADER_VIEW (focused_widget));
3290                 gboolean continue_download = FALSE;
3291                 gint num_of_unc_msgs;
3292
3293                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3294
3295                 if (num_of_unc_msgs) {
3296                         TnyAccount *account = get_account_from_header_list (header_list);
3297                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3298                         g_object_unref (account);
3299                 }
3300
3301                 if (num_of_unc_msgs == 0 || continue_download) {
3302                         modest_platform_information_banner (
3303                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3304                         modest_header_view_copy_selection (
3305                                         MODEST_HEADER_VIEW (focused_widget));
3306                 } else
3307                         copied = FALSE;
3308
3309                 g_object_unref (header_list);
3310
3311         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3312                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3313         }
3314
3315         /* Show information banner if there was a copy to clipboard */
3316         if(copied)
3317                 modest_platform_information_banner (
3318                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3319 }
3320
3321 void
3322 modest_ui_actions_on_undo (GtkAction *action,
3323                            ModestWindow *window)
3324 {
3325         ModestEmailClipboard *clipboard = NULL;
3326
3327         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3328                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3329         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3330                 /* Clear clipboard source */
3331                 clipboard = modest_runtime_get_email_clipboard ();
3332                 modest_email_clipboard_clear (clipboard);               
3333         }
3334         else {
3335                 g_return_if_reached ();
3336         }
3337 }
3338
3339 void
3340 modest_ui_actions_on_redo (GtkAction *action,
3341                            ModestWindow *window)
3342 {
3343         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3344                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3345         }
3346         else {
3347                 g_return_if_reached ();
3348         }
3349 }
3350
3351
3352 static void
3353 destroy_information_note (ModestMailOperation *mail_op, 
3354                           gpointer user_data)
3355 {
3356         /* destroy information note */
3357         gtk_widget_destroy (GTK_WIDGET(user_data));
3358 }
3359
3360 static void
3361 destroy_folder_information_note (ModestMailOperation *mail_op, 
3362                                  TnyFolder *new_folder,
3363                                  gpointer user_data)
3364 {
3365         /* destroy information note */
3366         gtk_widget_destroy (GTK_WIDGET(user_data));
3367 }
3368
3369
3370 static void
3371 paste_as_attachment_free (gpointer data)
3372 {
3373         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3374
3375         gtk_widget_destroy (helper->banner);
3376         g_object_unref (helper->banner);
3377         g_free (helper);
3378 }
3379
3380 static void
3381 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3382                             TnyHeader *header,
3383                             TnyMsg *msg,
3384                             gpointer userdata)
3385 {
3386         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3387         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3388
3389         if (msg == NULL)
3390                 return;
3391
3392         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3393         
3394 }
3395
3396 void
3397 modest_ui_actions_on_paste (GtkAction *action,
3398                             ModestWindow *window)
3399 {
3400         GtkWidget *focused_widget = NULL;
3401         GtkWidget *inf_note = NULL;
3402         ModestMailOperation *mail_op = NULL;
3403
3404         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3405         if (GTK_IS_EDITABLE (focused_widget)) {
3406                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3407         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3408                 ModestEmailClipboard *e_clipboard = NULL;
3409                 e_clipboard = modest_runtime_get_email_clipboard ();
3410                 if (modest_email_clipboard_cleared (e_clipboard)) {
3411                         GtkTextBuffer *buffer;
3412                         GtkClipboard *clipboard;
3413
3414                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3415                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3416                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3417                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3418                         ModestMailOperation *mail_op;
3419                         TnyFolder *src_folder;
3420                         TnyList *data;
3421                         gboolean delete;
3422                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3423                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3424                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3425                                                                            _CS("ckct_nw_pasting"));
3426                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3427                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3428                         if (helper->banner != NULL) {
3429                                 g_object_ref (G_OBJECT (helper->banner));
3430                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3431                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3432                         }
3433
3434                         if (data != NULL) {
3435                                 modest_mail_operation_get_msgs_full (mail_op, 
3436                                                                      data,
3437                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3438                                                                      helper,
3439                                                                      paste_as_attachment_free);
3440                         }
3441                 }
3442         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3443                 ModestEmailClipboard *clipboard = NULL;
3444                 TnyFolder *src_folder = NULL;
3445                 TnyFolderStore *folder_store = NULL;
3446                 TnyList *data = NULL;           
3447                 gboolean delete = FALSE;
3448                 
3449                 /* Check clipboard source */
3450                 clipboard = modest_runtime_get_email_clipboard ();
3451                 if (modest_email_clipboard_cleared (clipboard)) 
3452                         return;
3453                 
3454                 /* Get elements to paste */
3455                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3456
3457                 /* Create a new mail operation */
3458                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3459                 
3460                 /* Get destination folder */
3461                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3462
3463                 /* transfer messages  */
3464                 if (data != NULL) {
3465                         gint response = 0;
3466
3467                         /* Ask for user confirmation */
3468                         response = 
3469                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3470                                                                              TNY_FOLDER (folder_store), 
3471                                                                              delete,
3472                                                                              data);
3473                         
3474                         if (response == GTK_RESPONSE_OK) {
3475                                 /* Launch notification */
3476                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3477                                                                              _CS("ckct_nw_pasting"));
3478                                 if (inf_note != NULL)  {
3479                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3480                                         gtk_widget_show (GTK_WIDGET(inf_note));
3481                                 }
3482
3483                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3484                                 modest_mail_operation_xfer_msgs (mail_op, 
3485                                                                  data,
3486                                                                  TNY_FOLDER (folder_store),
3487                                                                  delete,
3488                                                                  destroy_information_note,
3489                                                                  inf_note);                             
3490                         } else {
3491                                 g_object_unref (mail_op);
3492                         }
3493                         
3494                 } else if (src_folder != NULL) {                        
3495                         /* Launch notification */
3496                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3497                                                                      _CS("ckct_nw_pasting"));
3498                         if (inf_note != NULL)  {
3499                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3500                                 gtk_widget_show (GTK_WIDGET(inf_note));
3501                         }
3502                         
3503                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3504                         modest_mail_operation_xfer_folder (mail_op, 
3505                                                            src_folder,
3506                                                            folder_store,
3507                                                            delete,
3508                                                            destroy_folder_information_note,
3509                                                            inf_note);
3510                 }
3511
3512                 /* Free */
3513                 if (data != NULL) 
3514                         g_object_unref (data);
3515                 if (src_folder != NULL) 
3516                         g_object_unref (src_folder);
3517                 if (folder_store != NULL) 
3518                         g_object_unref (folder_store);
3519         }
3520 }
3521
3522
3523 void
3524 modest_ui_actions_on_select_all (GtkAction *action,
3525                                  ModestWindow *window)
3526 {
3527         GtkWidget *focused_widget;
3528
3529         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3530         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3531                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3532         } else if (GTK_IS_LABEL (focused_widget)) {
3533                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3534         } else if (GTK_IS_EDITABLE (focused_widget)) {
3535                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3536         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3537                 GtkTextBuffer *buffer;
3538                 GtkTextIter start, end;
3539
3540                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3541                 gtk_text_buffer_get_start_iter (buffer, &start);
3542                 gtk_text_buffer_get_end_iter (buffer, &end);
3543                 gtk_text_buffer_select_range (buffer, &start, &end);
3544         } else if (GTK_IS_HTML (focused_widget)) {
3545                 gtk_html_select_all (GTK_HTML (focused_widget));
3546         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3547                 GtkWidget *header_view = focused_widget;
3548                 GtkTreeSelection *selection = NULL;
3549                 
3550                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3551                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3552                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3553                 }
3554                                 
3555                 /* Disable window dimming management */
3556                 modest_window_disable_dimming (MODEST_WINDOW(window));
3557                 
3558                 /* Select all messages */
3559                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3560                 gtk_tree_selection_select_all (selection);
3561
3562                 /* Set focuse on header view */
3563                 gtk_widget_grab_focus (header_view);
3564
3565
3566                 /* Enable window dimming management */
3567                 modest_window_enable_dimming (MODEST_WINDOW(window));
3568                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3569         }
3570
3571 }
3572
3573 void
3574 modest_ui_actions_on_mark_as_read (GtkAction *action,
3575                                    ModestWindow *window)
3576 {       
3577         g_return_if_fail (MODEST_IS_WINDOW(window));
3578                 
3579         /* Mark each header as read */
3580         do_headers_action (window, headers_action_mark_as_read, NULL);
3581 }
3582
3583 void
3584 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3585                                      ModestWindow *window)
3586 {       
3587         g_return_if_fail (MODEST_IS_WINDOW(window));
3588                 
3589         /* Mark each header as read */
3590         do_headers_action (window, headers_action_mark_as_unread, NULL);
3591 }
3592
3593 void
3594 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3595                                   GtkRadioAction *selected,
3596                                   ModestWindow *window)
3597 {
3598         gint value;
3599
3600         value = gtk_radio_action_get_current_value (selected);
3601         if (MODEST_IS_WINDOW (window)) {
3602                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3603         }
3604 }
3605
3606 void
3607 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3608                                                GtkRadioAction *selected,
3609                                                ModestWindow *window)
3610 {
3611         TnyHeaderFlags flags;
3612         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3613
3614         flags = gtk_radio_action_get_current_value (selected);
3615         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3616 }
3617
3618 void
3619 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3620                                                   GtkRadioAction *selected,
3621                                                   ModestWindow *window)
3622 {
3623         gint file_format;
3624
3625         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3626
3627         file_format = gtk_radio_action_get_current_value (selected);
3628         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3629 }
3630
3631
3632 void
3633 modest_ui_actions_on_zoom_plus (GtkAction *action,
3634                                 ModestWindow *window)
3635 {
3636         g_return_if_fail (MODEST_IS_WINDOW (window));
3637
3638         modest_window_zoom_plus (MODEST_WINDOW (window));
3639 }
3640
3641 void     
3642 modest_ui_actions_on_zoom_minus (GtkAction *action,
3643                                  ModestWindow *window)
3644 {
3645         g_return_if_fail (MODEST_IS_WINDOW (window));
3646
3647         modest_window_zoom_minus (MODEST_WINDOW (window));
3648 }
3649
3650 void     
3651 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3652                                            ModestWindow *window)
3653 {
3654         ModestWindowMgr *mgr;
3655         gboolean fullscreen, active;
3656         g_return_if_fail (MODEST_IS_WINDOW (window));
3657
3658         mgr = modest_runtime_get_window_mgr ();
3659
3660         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3661         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3662
3663         if (active != fullscreen) {
3664                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3665                 gtk_window_present (GTK_WINDOW (window));
3666         }
3667 }
3668
3669 void
3670 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3671                                         ModestWindow *window)
3672 {
3673         ModestWindowMgr *mgr;
3674         gboolean fullscreen;
3675
3676         g_return_if_fail (MODEST_IS_WINDOW (window));
3677
3678         mgr = modest_runtime_get_window_mgr ();
3679         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3680         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3681
3682         gtk_window_present (GTK_WINDOW (window));
3683 }
3684
3685 /* 
3686  * Used by modest_ui_actions_on_details to call do_headers_action 
3687  */
3688 static void
3689 headers_action_show_details (TnyHeader *header, 
3690                              ModestWindow *window,
3691                              gpointer user_data)
3692
3693 {
3694         GtkWidget *dialog;
3695         
3696         /* Create dialog */
3697         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3698
3699         /* Run dialog */
3700         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3701         gtk_widget_show_all (dialog);
3702         gtk_dialog_run (GTK_DIALOG (dialog));
3703
3704         gtk_widget_destroy (dialog);
3705 }
3706
3707 /*
3708  * Show the folder details in a ModestDetailsDialog widget
3709  */
3710 static void
3711 show_folder_details (TnyFolder *folder, 
3712                      GtkWindow *window)
3713 {
3714         GtkWidget *dialog;
3715         
3716         /* Create dialog */
3717         dialog = modest_details_dialog_new_with_folder (window, folder);
3718
3719         /* Run dialog */
3720         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3721         gtk_widget_show_all (dialog);
3722         gtk_dialog_run (GTK_DIALOG (dialog));
3723
3724         gtk_widget_destroy (dialog);
3725 }
3726
3727 /*
3728  * Show the header details in a ModestDetailsDialog widget
3729  */
3730 void     
3731 modest_ui_actions_on_details (GtkAction *action, 
3732                               ModestWindow *win)
3733 {
3734         TnyList * headers_list;
3735         TnyIterator *iter;
3736         TnyHeader *header;              
3737
3738         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3739                 TnyMsg *msg;
3740
3741                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3742                 if (!msg)
3743                         return;
3744                 g_object_unref (msg);           
3745
3746                 headers_list = get_selected_headers (win);
3747                 if (!headers_list)
3748                         return;
3749
3750                 iter = tny_list_create_iterator (headers_list);
3751
3752                 header = TNY_HEADER (tny_iterator_get_current (iter));
3753                 if (header) {
3754                         headers_action_show_details (header, win, NULL);
3755                         g_object_unref (header);
3756                 }
3757
3758                 g_object_unref (iter);
3759                 g_object_unref (headers_list);
3760
3761         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3762                 GtkWidget *folder_view, *header_view;
3763