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