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