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