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