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