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