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