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