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