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