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