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