3451b38734347a6e2241b028896844cc84033027
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 typedef struct _GetMsgAsyncHelper {     
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;     
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         GtkWidget *parent_window;
105 } ReplyForwardHelper;
106
107 typedef struct _MoveToHelper {
108         GtkTreeRowReference *reference;
109         GtkWidget *banner;
110 } MoveToHelper;
111
112 typedef struct _PasteAsAttachmentHelper {
113         ModestMsgEditWindow *window;
114         GtkWidget *banner;
115 } PasteAsAttachmentHelper;
116
117
118 /*
119  * The do_headers_action uses this kind of functions to perform some
120  * action to each member of a list of headers
121  */
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
123
124 static void     do_headers_action     (ModestWindow *win, 
125                                        HeadersFunc func,
126                                        gpointer user_data);
127
128 static void     open_msg_cb            (ModestMailOperation *mail_op, 
129                                         TnyHeader *header, 
130                                         gboolean canceled,
131                                         TnyMsg *msg,
132                                         GError *err,
133                                         gpointer user_data);
134
135 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
136                                         TnyHeader *header, 
137                                         gboolean canceled,
138                                         TnyMsg *msg,
139                                         GError *err,
140                                         gpointer user_data);
141
142 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
143
144 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
145                                         TnyFolder *folder, 
146                                         gpointer user_data);
147
148 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
149                                           gpointer user_data);
150
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
152
153 static gboolean connect_to_get_msg (ModestWindow *win,
154                                     gint num_of_uncached_msgs,
155                                     TnyAccount *account);
156
157 static gboolean remote_folder_is_pop (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_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1179                                                         _("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 } SendReceiveInfo;
1736
1737 static void
1738 do_send_receive_performer (gboolean canceled, 
1739                            GError *err,
1740                            GtkWindow *parent_window, 
1741                            TnyAccount *account, 
1742                            gpointer user_data)
1743 {
1744         ModestMailOperation *mail_op;
1745         SendReceiveInfo *info;
1746
1747         info = (SendReceiveInfo *) user_data;
1748
1749         if (err || canceled) {
1750                 goto clean;
1751         }
1752
1753         /* Set send/receive operation in progress */    
1754         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1755                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1756         }
1757         
1758         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1759                                                                  modest_ui_actions_send_receive_error_handler,
1760                                                                  NULL, NULL);
1761
1762         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1763                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1764                                   G_CALLBACK (on_send_receive_finished), 
1765                                   info->win);
1766
1767         /* Send & receive. */
1768         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1769         modest_mail_operation_update_account (mail_op, info->account_name, (info->win) ? FALSE : TRUE,
1770                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1771                                               new_messages_arrived, info->win);
1772         g_object_unref (G_OBJECT (mail_op));
1773         
1774  clean:
1775         /* Frees */
1776         if (info->account_name)
1777                 g_free (info->account_name);
1778         if (info->win)
1779                 g_object_unref (info->win);
1780         if (info->account)
1781                 g_object_unref (info->account);
1782         g_slice_free (SendReceiveInfo, info);
1783 }
1784
1785 /*
1786  * This function performs the send & receive required actions. The
1787  * window is used to create the mail operation. Typically it should
1788  * always be the main window, but we pass it as argument in order to
1789  * be more flexible.
1790  */
1791 void
1792 modest_ui_actions_do_send_receive (const gchar *account_name, 
1793                                    gboolean force_connection,
1794                                    ModestWindow *win)
1795 {
1796         gchar *acc_name = NULL;
1797         SendReceiveInfo *info;
1798         ModestTnyAccountStore *acc_store;
1799
1800         /* If no account name was provided then get the current account, and if
1801            there is no current account then pick the default one: */
1802         if (!account_name) {
1803                 if (win)
1804                         acc_name = g_strdup (modest_window_get_active_account (win));
1805                 if (!acc_name)
1806                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1807                 if (!acc_name) {
1808                         g_printerr ("modest: cannot get default account\n");
1809                         return;
1810                 }
1811         } else {
1812                 acc_name = g_strdup (account_name);
1813         }
1814
1815         acc_store = modest_runtime_get_account_store ();
1816
1817         /* Create the info for the connect and perform */
1818         info = g_slice_new (SendReceiveInfo);
1819         info->account_name = acc_name;
1820         info->win = (win) ? g_object_ref (win) : NULL;
1821         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1822                                                                      TNY_ACCOUNT_TYPE_STORE);
1823
1824         /* Invoke the connect and perform */
1825         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
1826                                              force_connection, info->account, 
1827                                              do_send_receive_performer, info);
1828 }
1829
1830
1831 static void
1832 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1833                                   ModestWindow *win)
1834 {
1835         TnyTransportAccount *transport_account;
1836         TnySendQueue *send_queue = NULL;
1837         GError *error = NULL;
1838
1839         /* Get transport account */
1840         transport_account =
1841                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1842                                       (modest_runtime_get_account_store(),
1843                                        account_name,
1844                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1845         if (!transport_account) {
1846                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1847                 goto frees;
1848         }
1849
1850         /* Get send queue*/
1851         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1852         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1853                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1854                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1855                              "modest: could not find send queue for account\n");
1856         } else {
1857                 /* Cancel the current send */
1858                 tny_account_cancel (TNY_ACCOUNT (transport_account));
1859
1860                 /* Suspend all pending messages */
1861                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
1862         }
1863
1864  frees:
1865         if (transport_account != NULL) 
1866                 g_object_unref (G_OBJECT (transport_account));
1867 }
1868
1869 static void
1870 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1871 {
1872         GSList *account_names, *iter;
1873
1874         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1875                                                           TRUE);
1876
1877         iter = account_names;
1878         while (iter) {                  
1879                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1880                 iter = g_slist_next (iter);
1881         }
1882
1883         modest_account_mgr_free_account_names (account_names);
1884         account_names = NULL;
1885 }
1886
1887 void
1888 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1889
1890 {
1891         /* Check if accounts exist */
1892         gboolean accounts_exist = 
1893                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1894         
1895         /* If not, allow the user to create an account before trying to send/receive. */
1896         if (!accounts_exist)
1897                 modest_ui_actions_on_accounts (NULL, win);
1898         
1899         /* Cancel all sending operaitons */     
1900         modest_ui_actions_cancel_send_all (win);
1901 }
1902
1903 /*
1904  * Refreshes all accounts. This function will be used by automatic
1905  * updates
1906  */
1907 void
1908 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
1909                                        gboolean force_connection)
1910 {
1911         GSList *account_names, *iter;
1912
1913         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1914                                                           TRUE);
1915
1916         iter = account_names;
1917         while (iter) {                  
1918                 modest_ui_actions_do_send_receive ((const char*) iter->data, force_connection, win);
1919                 iter = g_slist_next (iter);
1920         }
1921
1922         modest_account_mgr_free_account_names (account_names);
1923         account_names = NULL;
1924 }
1925
1926 /*
1927  * Handler of the click on Send&Receive button in the main toolbar
1928  */
1929 void
1930 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1931 {
1932         /* Check if accounts exist */
1933         gboolean accounts_exist;
1934
1935         accounts_exist =
1936                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1937         
1938         /* If not, allow the user to create an account before trying to send/receive. */
1939         if (!accounts_exist)
1940                 modest_ui_actions_on_accounts (NULL, win);
1941         
1942         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1943         if (MODEST_IS_MAIN_WINDOW (win)) {
1944                 GtkWidget *folder_view;
1945                 TnyFolderStore *folder_store;
1946
1947                 folder_view = 
1948                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1949                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1950                 if (!folder_view)
1951                         return;
1952                 
1953                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1954         
1955                 if (folder_store)
1956                         g_object_unref (folder_store);
1957         }       
1958         
1959         /* Refresh the active account. Force the connection if needed */
1960         modest_ui_actions_do_send_receive (NULL, TRUE, win);
1961 }
1962
1963
1964 void
1965 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1966 {
1967         ModestConf *conf;
1968         GtkWidget *header_view;
1969         
1970         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1971
1972         header_view = modest_main_window_get_child_widget (main_window,
1973                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1974         if (!header_view)
1975                 return;
1976
1977         conf = modest_runtime_get_conf ();
1978         
1979         /* what is saved/restored is depending on the style; thus; we save with
1980          * old style, then update the style, and restore for this new style
1981          */
1982         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1983         
1984         if (modest_header_view_get_style
1985             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1986                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1987                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1988         else
1989                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1990                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1991
1992         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1993                                       MODEST_CONF_HEADER_VIEW_KEY);
1994 }
1995
1996
1997 void 
1998 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1999                                       TnyHeader *header,
2000                                       ModestMainWindow *main_window)
2001 {
2002         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2003         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2004         
2005         /* in the case the folder is empty, show the empty folder message and focus
2006          * folder view */
2007         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2008                 if (modest_header_view_is_empty (header_view)) {
2009                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2010                         GtkWidget *folder_view = 
2011                                 modest_main_window_get_child_widget (main_window,
2012                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2013                         if (folder != NULL) 
2014                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2015                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2016                         return;
2017                 }
2018         }
2019         /* If no header has been selected then exit */
2020         if (!header)
2021                 return;
2022
2023         /* Update focus */
2024         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2025             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2026
2027         /* Update toolbar dimming state */
2028         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2029 }
2030
2031 void
2032 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2033                                        TnyHeader *header,
2034                                        ModestMainWindow *main_window)
2035 {
2036         TnyList *headers;
2037
2038         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2039
2040         if (!header)
2041                 return;
2042
2043         if (modest_header_view_count_selected_headers (header_view) > 1) {
2044                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2045                 return;
2046         }
2047
2048
2049 /*      headers = tny_simple_list_new (); */
2050 /*      tny_list_prepend (headers, G_OBJECT (header)); */
2051         headers = modest_header_view_get_selected_headers (header_view);
2052
2053         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2054
2055         g_object_unref (headers);
2056 }
2057
2058 static void
2059 set_active_account_from_tny_account (TnyAccount *account,
2060                                      ModestWindow *window)
2061 {
2062         const gchar *server_acc_name = tny_account_get_id (account);
2063         
2064         /* We need the TnyAccount provided by the
2065            account store because that is the one that
2066            knows the name of the Modest account */
2067         TnyAccount *modest_server_account = modest_server_account = 
2068                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2069                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2070                                                              server_acc_name);
2071         if (!modest_server_account) {
2072                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2073                 return;
2074         }
2075
2076         /* Update active account, but only if it's not a pseudo-account */
2077         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2078             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2079                 const gchar *modest_acc_name = 
2080                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2081                 if (modest_acc_name)
2082                         modest_window_set_active_account (window, modest_acc_name);
2083         }
2084         
2085         g_object_unref (modest_server_account);
2086 }
2087
2088
2089 static void
2090 folder_refreshed_cb (ModestMailOperation *mail_op, 
2091                      TnyFolder *folder, 
2092                      gpointer user_data)
2093 {
2094         ModestMainWindow *win = NULL;
2095         GtkWidget *header_view;
2096
2097         g_return_if_fail (TNY_IS_FOLDER (folder));
2098
2099         win = MODEST_MAIN_WINDOW (user_data);
2100         header_view = 
2101                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2102
2103         if (header_view) {
2104                 TnyFolder *current_folder;
2105
2106                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2107                 if (current_folder != NULL && folder != current_folder) {
2108                         g_object_unref (current_folder);
2109                         return;
2110                 } else if (current_folder)
2111                         g_object_unref (current_folder);
2112         }
2113
2114         /* Check if folder is empty and set headers view contents style */
2115         if (tny_folder_get_all_count (folder) == 0)
2116                 modest_main_window_set_contents_style (win,
2117                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2118 }
2119
2120 void 
2121 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2122                                                TnyFolderStore *folder_store, 
2123                                                gboolean selected,
2124                                                ModestMainWindow *main_window)
2125 {
2126         ModestConf *conf;
2127         GtkWidget *header_view;
2128
2129         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2130
2131         header_view = modest_main_window_get_child_widget(main_window,
2132                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2133         if (!header_view)
2134                 return;
2135         
2136         conf = modest_runtime_get_conf ();
2137
2138         if (TNY_IS_ACCOUNT (folder_store)) {
2139                 if (selected) {
2140                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2141                         
2142                         /* Show account details */
2143                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2144                 }
2145         } else {
2146                 if (TNY_IS_FOLDER (folder_store) && selected) {
2147                         
2148                         /* Update the active account */
2149                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2150                         if (account) {
2151                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2152                                 g_object_unref (account);
2153                                 account = NULL;
2154                         }
2155
2156                         /* Set the header style by default, it could
2157                            be changed later by the refresh callback to
2158                            empty */
2159                         modest_main_window_set_contents_style (main_window, 
2160                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2161
2162                         /* Set folder on header view. This function
2163                            will call tny_folder_refresh_async so we
2164                            pass a callback that will be called when
2165                            finished. We use that callback to set the
2166                            empty view if there are no messages */
2167                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2168                                                        TNY_FOLDER (folder_store),
2169                                                        folder_refreshed_cb,
2170                                                        main_window);
2171                         
2172                         /* Restore configuration. We need to do this
2173                            *after* the set_folder because the widget
2174                            memory asks the header view about its
2175                            folder  */
2176                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2177                                                       G_OBJECT(header_view),
2178                                                       MODEST_CONF_HEADER_VIEW_KEY);
2179                 } else {
2180                         /* Update the active account */
2181                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2182                         /* Save only if we're seeing headers */
2183                         if (modest_main_window_get_contents_style (main_window) ==
2184                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2185                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2186                                                            MODEST_CONF_HEADER_VIEW_KEY);
2187                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2188                 }
2189         }
2190
2191         /* Update toolbar dimming state */
2192         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2193 }
2194
2195 void 
2196 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2197                                      ModestWindow *win)
2198 {
2199         GtkWidget *dialog;
2200         gchar *txt, *item;
2201         gboolean online;
2202
2203         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2204         
2205         online = tny_device_is_online (modest_runtime_get_device());
2206
2207         if (online) {
2208                 /* already online -- the item is simply not there... */
2209                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2210                                                  GTK_DIALOG_MODAL,
2211                                                  GTK_MESSAGE_WARNING,
2212                                                  GTK_BUTTONS_NONE,
2213                                                  _("The %s you selected cannot be found"),
2214                                                  item);
2215                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2216                 gtk_dialog_run (GTK_DIALOG(dialog));
2217         } else {
2218                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2219                                                       GTK_WINDOW (win),
2220                                                       GTK_DIALOG_MODAL,
2221                                                       _("mcen_bd_dialog_cancel"),
2222                                                       GTK_RESPONSE_REJECT,
2223                                                       _("mcen_bd_dialog_ok"),
2224                                                       GTK_RESPONSE_ACCEPT,
2225                                                       NULL);
2226                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2227                                          "Do you want to get online?"), item);
2228                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2229                                     gtk_label_new (txt), FALSE, FALSE, 0);
2230                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2231                 g_free (txt);
2232
2233                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2234                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2235                         /* TODO: Comment about why is this commented out: */
2236                         /* modest_platform_connect_and_wait (); */
2237                 }
2238         }
2239         gtk_widget_destroy (dialog);
2240 }
2241
2242 void
2243 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2244                                      ModestWindow *win)
2245 {
2246         /* g_message ("%s %s", __FUNCTION__, link); */
2247 }       
2248
2249
2250 void
2251 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2252                                         ModestWindow *win)
2253 {
2254         modest_platform_activate_uri (link);
2255 }
2256
2257 void
2258 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2259                                           ModestWindow *win)
2260 {
2261         modest_platform_show_uri_popup (link);
2262 }
2263
2264 void
2265 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2266                                              ModestWindow *win)
2267 {
2268         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2269 }
2270
2271 void
2272 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2273                                           const gchar *address,
2274                                           ModestWindow *win)
2275 {
2276         /* g_message ("%s %s", __FUNCTION__, address); */
2277 }
2278
2279 static void
2280 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2281                       TnyMsg *saved_draft,
2282                       gpointer user_data)
2283 {
2284         ModestMsgEditWindow *edit_window;
2285         ModestMainWindow *win;
2286
2287         /* FIXME. Make the header view sensitive again. This is a
2288          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2289          * for details */
2290         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2291                                          modest_runtime_get_window_mgr(), FALSE));
2292         if (win != NULL) {
2293                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2294                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2295                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2296         }
2297
2298         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2299
2300         /* It might not be a good idea to do nothing if there was an error,
2301          * so let's at least show a generic error banner. */
2302         /* TODO error while saving attachment, show "Saving draft failed" banner */
2303         if (modest_mail_operation_get_error (mail_op) != NULL) {
2304                 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_op))->message);
2305                 modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
2306         } else {
2307                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2308         }
2309         g_object_unref(edit_window);
2310 }
2311
2312 gboolean
2313 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2314 {
2315         TnyTransportAccount *transport_account;
2316         ModestMailOperation *mail_operation;
2317         MsgData *data;
2318         gchar *account_name, *from;
2319         ModestAccountMgr *account_mgr;
2320 /*      char *info_text; */
2321         gboolean had_error = FALSE;
2322         guint64 available_disk, expected_size;
2323         gint parts_count;
2324         guint64 parts_size;
2325         ModestMainWindow *win;
2326
2327         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2328         
2329         data = modest_msg_edit_window_get_msg_data (edit_window);
2330
2331         /* Check size */
2332         available_disk = modest_folder_available_space (NULL);
2333         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2334         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2335                                                  data->html_body,
2336                                                  parts_count,
2337                                                  parts_size);
2338
2339         if ((available_disk != -1) && expected_size > available_disk) {
2340                 modest_msg_edit_window_free_msg_data (edit_window, data);
2341
2342                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2343                 return FALSE;
2344         }
2345
2346         account_name = g_strdup (data->account_name);
2347         account_mgr = modest_runtime_get_account_mgr();
2348         if (!account_name)
2349                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2350         if (!account_name) 
2351                 account_name = modest_account_mgr_get_default_account (account_mgr);
2352         if (!account_name) {
2353                 g_printerr ("modest: no account found\n");
2354                 modest_msg_edit_window_free_msg_data (edit_window, data);
2355                 return FALSE;
2356         }
2357
2358         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2359                 account_name = g_strdup (data->account_name);
2360         }
2361
2362         transport_account =
2363                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2364                                       (modest_runtime_get_account_store(),
2365                                        account_name,
2366                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2367         if (!transport_account) {
2368                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2369                 g_free (account_name);
2370                 modest_msg_edit_window_free_msg_data (edit_window, data);
2371                 return FALSE;
2372         }
2373         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2374
2375         /* Create the mail operation */         
2376         mail_operation = modest_mail_operation_new (NULL);
2377         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2378
2379         modest_mail_operation_save_to_drafts (mail_operation,
2380                                               transport_account,
2381                                               data->draft_msg,
2382                                               from,
2383                                               data->to, 
2384                                               data->cc, 
2385                                               data->bcc,
2386                                               data->subject, 
2387                                               data->plain_body, 
2388                                               data->html_body,
2389                                               data->attachments,
2390                                               data->images,
2391                                               data->priority_flags,
2392                                               on_save_to_drafts_cb,
2393                                               g_object_ref(edit_window));
2394
2395         /* Use the main window as the parent of the banner, if the
2396            main window does not exist it won't be shown, if the parent
2397            window exists then it's properly shown. We don't use the
2398            editor window because it could be closed (save to drafts
2399            could happen after closing the window */
2400         win = (ModestMainWindow *)
2401                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2402         if (win) {
2403                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2404                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2405                 g_free (text);
2406         }
2407         modest_msg_edit_window_set_modified (edit_window, FALSE);
2408
2409         /* Frees */
2410         g_free (from);
2411         g_free (account_name);
2412         g_object_unref (G_OBJECT (transport_account));
2413         g_object_unref (G_OBJECT (mail_operation));
2414
2415         modest_msg_edit_window_free_msg_data (edit_window, data);
2416
2417         /* ** FIXME **
2418          * If the drafts folder is selected then make the header view
2419          * insensitive while the message is being saved to drafts
2420          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2421          * is not very clean but it avoids letting the drafts folder
2422          * in an inconsistent state: the user could edit the message
2423          * being saved and undesirable things would happen.
2424          * In the average case the user won't notice anything at
2425          * all. In the worst case (the user is editing a really big
2426          * file from Drafts) the header view will be insensitive
2427          * during the saving process (10 or 20 seconds, depending on
2428          * the message). Anyway this is just a quick workaround: once
2429          * we find a better solution it should be removed
2430          * See NB#65125 (commend #18) for details.
2431          */
2432         if (!had_error && win != NULL) {
2433                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2434                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2435                 if (view != NULL) {
2436                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2437                         if (folder) {
2438                                 if (modest_tny_folder_is_local_folder(folder)) {
2439                                         TnyFolderType folder_type;
2440                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2441                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2442                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2443                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2444                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2445                                         }
2446                                 }
2447                         }
2448                         if (folder != NULL) g_object_unref(folder);
2449                 }
2450         }
2451
2452         return !had_error;
2453 }
2454
2455 /* For instance, when clicking the Send toolbar button when editing a message: */
2456 gboolean
2457 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2458 {
2459         TnyTransportAccount *transport_account = NULL;
2460         gboolean had_error = FALSE;
2461         guint64 available_disk, expected_size;
2462         gint parts_count;
2463         guint64 parts_size;
2464
2465         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2466
2467         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2468                 return TRUE;
2469         
2470         /* FIXME: Code added just for testing. The final version will
2471            use the send queue provided by tinymail and some
2472            classifier */
2473         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2474
2475         /* Check size */
2476         available_disk = modest_folder_available_space (NULL);
2477         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2478         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2479                                                  data->html_body,
2480                                                  parts_count,
2481                                                  parts_size);
2482
2483         if ((available_disk != -1) && expected_size > available_disk) {
2484                 modest_msg_edit_window_free_msg_data (edit_window, data);
2485
2486                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2487                 return FALSE;
2488         }
2489
2490         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2491         gchar *account_name = g_strdup (data->account_name);
2492         if (!account_name)
2493                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2494
2495         if (!account_name) 
2496                 account_name = modest_account_mgr_get_default_account (account_mgr);
2497                 
2498         if (!account_name) {
2499                 modest_msg_edit_window_free_msg_data (edit_window, data);
2500                 /* Run account setup wizard */
2501                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2502                         return TRUE;
2503                 }
2504         }
2505         
2506         /* Get the currently-active transport account for this modest account: */
2507         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2508                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2509                                                           (modest_runtime_get_account_store(),
2510                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2511         }
2512         
2513         if (!transport_account) {
2514                 modest_msg_edit_window_free_msg_data (edit_window, data);
2515                 /* Run account setup wizard */
2516                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2517                         return TRUE;
2518         }
2519         
2520         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2521
2522         /* Create the mail operation */
2523         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2524         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2525
2526         modest_mail_operation_send_new_mail (mail_operation,
2527                                              transport_account,
2528                                              data->draft_msg,
2529                                              from,
2530                                              data->to, 
2531                                              data->cc, 
2532                                              data->bcc,
2533                                              data->subject, 
2534                                              data->plain_body, 
2535                                              data->html_body,
2536                                              data->attachments,
2537                                              data->images,
2538                                              data->priority_flags);
2539
2540         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2541                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2542
2543
2544         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2545                 const GError *error = modest_mail_operation_get_error (mail_operation);
2546                 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2547                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2548                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2549                         had_error = TRUE;
2550                 }
2551         }
2552                                              
2553         /* Free data: */
2554         g_free (from);
2555         g_free (account_name);
2556         g_object_unref (G_OBJECT (transport_account));
2557         g_object_unref (G_OBJECT (mail_operation));
2558
2559         modest_msg_edit_window_free_msg_data (edit_window, data);
2560
2561         if (!had_error) {
2562                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2563
2564                 /* Save settings and close the window: */
2565                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2566         }
2567
2568         return !had_error;
2569 }
2570
2571 void 
2572 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2573                                   ModestMsgEditWindow *window)
2574 {
2575         ModestMsgEditFormatState *format_state = NULL;
2576
2577         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2578         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2579
2580         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2581                 return;
2582
2583         format_state = modest_msg_edit_window_get_format_state (window);
2584         g_return_if_fail (format_state != NULL);
2585
2586         format_state->bold = gtk_toggle_action_get_active (action);
2587         modest_msg_edit_window_set_format_state (window, format_state);
2588         g_free (format_state);
2589         
2590 }
2591
2592 void 
2593 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2594                                      ModestMsgEditWindow *window)
2595 {
2596         ModestMsgEditFormatState *format_state = NULL;
2597
2598         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2599         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2600
2601         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2602                 return;
2603
2604         format_state = modest_msg_edit_window_get_format_state (window);
2605         g_return_if_fail (format_state != NULL);
2606
2607         format_state->italics = gtk_toggle_action_get_active (action);
2608         modest_msg_edit_window_set_format_state (window, format_state);
2609         g_free (format_state);
2610         
2611 }
2612
2613 void 
2614 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2615                                      ModestMsgEditWindow *window)
2616 {
2617         ModestMsgEditFormatState *format_state = NULL;
2618
2619         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2620         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2621
2622         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2623                 return;
2624
2625         format_state = modest_msg_edit_window_get_format_state (window);
2626         g_return_if_fail (format_state != NULL);
2627
2628         format_state->bullet = gtk_toggle_action_get_active (action);
2629         modest_msg_edit_window_set_format_state (window, format_state);
2630         g_free (format_state);
2631         
2632 }
2633
2634 void 
2635 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2636                                      GtkRadioAction *selected,
2637                                      ModestMsgEditWindow *window)
2638 {
2639         ModestMsgEditFormatState *format_state = NULL;
2640         GtkJustification value;
2641
2642         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2643
2644         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2645                 return;
2646
2647         value = gtk_radio_action_get_current_value (selected);
2648
2649         format_state = modest_msg_edit_window_get_format_state (window);
2650         g_return_if_fail (format_state != NULL);
2651
2652         format_state->justification = value;
2653         modest_msg_edit_window_set_format_state (window, format_state);
2654         g_free (format_state);
2655 }
2656
2657 void 
2658 modest_ui_actions_on_select_editor_color (GtkAction *action,
2659                                           ModestMsgEditWindow *window)
2660 {
2661         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2662         g_return_if_fail (GTK_IS_ACTION (action));
2663
2664         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2665                 return;
2666
2667         modest_msg_edit_window_select_color (window);
2668 }
2669
2670 void 
2671 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2672                                                      ModestMsgEditWindow *window)
2673 {
2674         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2675         g_return_if_fail (GTK_IS_ACTION (action));
2676
2677         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2678                 return;
2679
2680         modest_msg_edit_window_select_background_color (window);
2681 }
2682
2683 void 
2684 modest_ui_actions_on_insert_image (GtkAction *action,
2685                                    ModestMsgEditWindow *window)
2686 {
2687         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2688         g_return_if_fail (GTK_IS_ACTION (action));
2689
2690         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2691                 return;
2692
2693         modest_msg_edit_window_insert_image (window);
2694 }
2695
2696 void 
2697 modest_ui_actions_on_attach_file (GtkAction *action,
2698                                   ModestMsgEditWindow *window)
2699 {
2700         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2701         g_return_if_fail (GTK_IS_ACTION (action));
2702
2703         modest_msg_edit_window_offer_attach_file (window);
2704 }
2705
2706 void 
2707 modest_ui_actions_on_remove_attachments (GtkAction *action,
2708                                          ModestMsgEditWindow *window)
2709 {
2710         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2711         g_return_if_fail (GTK_IS_ACTION (action));
2712
2713         modest_msg_edit_window_remove_attachments (window, NULL);
2714 }
2715
2716 static void
2717 do_create_folder_cb (ModestMailOperation *mail_op,
2718                      TnyFolderStore *parent_folder, 
2719                      TnyFolder *new_folder,
2720                      gpointer user_data)
2721 {
2722         gchar *suggested_name = (gchar *) user_data;
2723         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2724
2725         if (modest_mail_operation_get_error (mail_op)) {
2726                 /* Show an error */
2727                 modest_platform_information_banner (GTK_WIDGET (source_win), NULL,
2728                                                     _("mail_in_ui_folder_create_error"));
2729
2730                 /* Try again */
2731                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2732         } else {
2733                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2734                  * FIXME: any other? */         
2735                 GtkWidget *folder_view;
2736
2737                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2738                         folder_view = 
2739                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2740                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2741                 else
2742                         folder_view =
2743                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2744                 
2745                 /* Select the newly created folder */
2746                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2747                                                   new_folder, FALSE);
2748                 g_object_unref (new_folder);
2749         }
2750         /* Free. Note that the first time it'll be NULL so noop */
2751         g_free (suggested_name);
2752         g_object_unref (source_win);
2753 }
2754
2755 static void
2756 do_create_folder (GtkWindow *parent_window, 
2757                   TnyFolderStore *parent_folder, 
2758                   const gchar *suggested_name)
2759 {
2760         gint result;
2761         gchar *folder_name = NULL;
2762
2763         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2764                                                         parent_folder,
2765                                                         (gchar *) suggested_name,
2766                                                         &folder_name);
2767         
2768         if (result == GTK_RESPONSE_ACCEPT) {
2769                 ModestMailOperation *mail_op;
2770                 
2771                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2772                         
2773                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2774                                                  mail_op);
2775                 modest_mail_operation_create_folder (mail_op,
2776                                                      parent_folder,
2777                                                      (const gchar *) folder_name,
2778                                                      do_create_folder_cb,
2779                                                      folder_name);
2780                 g_object_unref (mail_op);
2781         }
2782 }
2783
2784 static void
2785 create_folder_performer (gboolean canceled, 
2786                          GError *err,
2787                          GtkWindow *parent_window, 
2788                          TnyAccount *account, 
2789                          gpointer user_data)
2790 {
2791         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2792
2793         if (canceled || err) {
2794                 goto frees;
2795         }
2796
2797         /* Run the new folder dialog */
2798         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2799
2800  frees:
2801         g_object_unref (parent_folder);
2802 }
2803
2804 static void
2805 modest_ui_actions_create_folder(GtkWidget *parent_window,
2806                                 GtkWidget *folder_view)
2807 {
2808         TnyFolderStore *parent_folder;
2809
2810         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2811         
2812         if (parent_folder) {
2813                 /* The parent folder will be freed in the callback */
2814                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2815                                                                TRUE,
2816                                                                parent_folder,
2817                                                                create_folder_performer, 
2818                                                                parent_folder);
2819         }
2820 }
2821
2822 void 
2823 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2824 {
2825         GtkWidget *folder_view;
2826         
2827         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2828
2829         folder_view = modest_main_window_get_child_widget (main_window,
2830                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2831         if (!folder_view)
2832                 return;
2833
2834         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2835 }
2836
2837 static void
2838 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2839                                                gpointer user_data)
2840 {
2841         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2842         const GError *error = NULL;
2843         const gchar *message = NULL;
2844         
2845         /* Get error message */
2846         error = modest_mail_operation_get_error (mail_op);
2847         if (!error)
2848                 g_return_if_reached ();
2849
2850         switch (error->code) {
2851         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2852                 message = _CS("ckdg_ib_folder_already_exists");
2853                 break;
2854         default:
2855                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2856                            error->code, error->message);
2857                 return;
2858         }
2859
2860         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2861 }
2862
2863 typedef struct {
2864         TnyFolderStore *folder;
2865         gchar *new_name;
2866 } RenameFolderInfo;
2867
2868 static void
2869 on_rename_folder_cb (ModestMailOperation *mail_op, 
2870                      TnyFolder *new_folder,
2871                      gpointer user_data)
2872 {
2873         /* Select now */
2874         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2875                                           new_folder, FALSE);
2876 }
2877
2878 static void
2879 on_rename_folder_performer (gboolean canceled, 
2880                             GError *err, 
2881                             GtkWindow *parent_window, 
2882                             TnyAccount *account, 
2883                             gpointer user_data)
2884 {
2885         ModestMailOperation *mail_op = NULL;
2886         GtkTreeSelection *sel = NULL;
2887         GtkWidget *folder_view = NULL;
2888         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2889
2890         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2891
2892                 folder_view = modest_main_window_get_child_widget (
2893                                 MODEST_MAIN_WINDOW (parent_window),
2894                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2895
2896                 mail_op = 
2897                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2898                                         modest_ui_actions_rename_folder_error_handler,
2899                                         parent_window, NULL);
2900
2901                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2902                                 mail_op);
2903
2904                 /* Clear the headers view */
2905                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2906                 gtk_tree_selection_unselect_all (sel);
2907
2908                 /* Actually rename the folder */
2909                 modest_mail_operation_rename_folder (mail_op,
2910                                                      TNY_FOLDER (data->folder),
2911                                                      (const gchar *) (data->new_name),
2912                                                      on_rename_folder_cb,
2913                                                      folder_view);
2914         }
2915
2916         g_object_unref (mail_op);
2917         g_free (data->new_name);
2918         g_free (data);
2919 }
2920
2921 void 
2922 modest_ui_actions_on_rename_folder (GtkAction *action,
2923                                      ModestMainWindow *main_window)
2924 {
2925         TnyFolderStore *folder;
2926         GtkWidget *folder_view;
2927         GtkWidget *header_view; 
2928
2929         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2930
2931         folder_view = modest_main_window_get_child_widget (main_window,
2932                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2933         if (!folder_view)
2934                 return;
2935
2936         header_view = modest_main_window_get_child_widget (main_window,
2937                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2938         
2939         if (!header_view)
2940                 return;
2941
2942         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2943
2944         if (!folder)
2945                 return;
2946
2947         if (TNY_IS_FOLDER (folder)) {
2948                 gchar *folder_name;
2949                 gint response;
2950                 const gchar *current_name;
2951                 TnyFolderStore *parent;
2952                 gboolean do_rename = TRUE;
2953
2954                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2955                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2956                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2957                                                                      parent, current_name, 
2958                                                                      &folder_name);
2959                 g_object_unref (parent);
2960
2961                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2962                         do_rename = FALSE;
2963                 } else {
2964                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2965                         rename_folder_data->folder = folder;
2966                         rename_folder_data->new_name = folder_name;
2967                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
2968                                         folder, on_rename_folder_performer, rename_folder_data);
2969                 }
2970         }
2971         g_object_unref (folder);
2972 }
2973
2974 static void
2975 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2976                                                gpointer user_data)
2977 {
2978         GObject *win = modest_mail_operation_get_source (mail_op);
2979
2980         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2981                                                 _("mail_in_ui_folder_delete_error"));
2982         g_object_unref (win);
2983 }
2984
2985 typedef struct {
2986         TnyFolderStore *folder;
2987         gboolean move_to_trash;
2988 } DeleteFolderInfo;
2989
2990 static void
2991 on_delete_folder_cb (gboolean canceled, 
2992                   GError *err,
2993                   GtkWindow *parent_window, 
2994                   TnyAccount *account, 
2995                   gpointer user_data)
2996 {
2997         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
2998         GtkWidget *folder_view;
2999         ModestMailOperation *mail_op;
3000         GtkTreeSelection *sel;
3001         
3002         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3003                 g_object_unref (G_OBJECT (info->folder));
3004                 g_free (info);
3005                 return;
3006         }
3007         
3008         folder_view = modest_main_window_get_child_widget (
3009                         MODEST_MAIN_WINDOW (parent_window),
3010                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3011
3012         /* Unselect the folder before deleting it to free the headers */
3013         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3014         gtk_tree_selection_unselect_all (sel);
3015
3016         /* Create the mail operation */
3017         mail_op =
3018                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3019                                 modest_ui_actions_delete_folder_error_handler,
3020                                 NULL, NULL);
3021
3022         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3023                         mail_op);
3024         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3025         
3026         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3027
3028         g_object_unref (G_OBJECT (mail_op));
3029         g_object_unref (G_OBJECT (info->folder));
3030         g_free (info);
3031 }
3032
3033 static void
3034 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3035 {
3036         TnyFolderStore *folder;
3037         GtkWidget *folder_view;
3038         gint response;
3039         gchar *message;
3040         
3041         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3042
3043         folder_view = modest_main_window_get_child_widget (main_window,
3044                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3045         if (!folder_view)
3046                 return;
3047
3048         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3049
3050         /* Show an error if it's an account */
3051         if (!TNY_IS_FOLDER (folder)) {
3052                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3053                                                         _("mail_in_ui_folder_delete_error"));
3054                 g_object_unref (G_OBJECT (folder));
3055                 return;
3056         }
3057
3058         /* Ask the user */      
3059         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3060                                     tny_folder_get_name (TNY_FOLDER (folder)));
3061         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3062                                                             (const gchar *) message);
3063         g_free (message);
3064
3065         if (response == GTK_RESPONSE_OK) {
3066                 DeleteFolderInfo *info;
3067                 info = g_new0(DeleteFolderInfo, 1);
3068                 info->folder = folder;
3069                 info->move_to_trash = move_to_trash;
3070                 g_object_ref (G_OBJECT (info->folder));
3071                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3072                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3073                                                                TRUE,
3074                                                                TNY_FOLDER_STORE (account), 
3075                                                                on_delete_folder_cb, info);
3076                 g_object_unref (account);
3077         }
3078         g_object_unref (G_OBJECT (folder));
3079 }
3080
3081 void 
3082 modest_ui_actions_on_delete_folder (GtkAction *action,
3083                                      ModestMainWindow *main_window)
3084 {
3085         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3086         
3087         delete_folder (main_window, FALSE);
3088 }
3089
3090 void 
3091 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3092 {
3093         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3094         
3095         delete_folder (main_window, TRUE);
3096 }
3097
3098
3099 void
3100 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3101                                          const gchar* server_account_name,
3102                                          gchar **username,
3103                                          gchar **password, 
3104                                          gboolean *cancel, 
3105                                          gboolean *remember,
3106                                          ModestMainWindow *main_window)
3107 {
3108         g_return_if_fail(server_account_name);
3109         gboolean completed = FALSE;
3110         
3111         /* Initalize output parameters: */
3112         if (cancel)
3113                 *cancel = FALSE;
3114                 
3115         if (remember)
3116                 *remember = TRUE;
3117                 
3118 #ifdef MODEST_PLATFORM_MAEMO
3119         /* Maemo uses a different (awkward) button order,
3120          * It should probably just use gtk_alternative_dialog_button_order ().
3121          */
3122         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3123                                               NULL,
3124                                               GTK_DIALOG_MODAL,
3125                                               _("mcen_bd_dialog_ok"),
3126                                               GTK_RESPONSE_ACCEPT,
3127                                               _("mcen_bd_dialog_cancel"),
3128                                               GTK_RESPONSE_REJECT,
3129                                               NULL);
3130 #else
3131         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3132                                               NULL,
3133                                               GTK_DIALOG_MODAL,
3134                                               GTK_STOCK_CANCEL,
3135                                               GTK_RESPONSE_REJECT,
3136                                               GTK_STOCK_OK,
3137                                               GTK_RESPONSE_ACCEPT,
3138                                               NULL);
3139 #endif /* MODEST_PLATFORM_MAEMO */
3140
3141         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3142         
3143         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3144                 modest_runtime_get_account_mgr(), server_account_name);
3145         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3146                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3147                 if (cancel)
3148                         *cancel = TRUE;
3149                 return;
3150         }
3151         
3152         /* This causes a warning because the logical ID has no %s in it, 
3153          * though the translation does, but there is not much we can do about that: */
3154         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3155         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3156                             FALSE, FALSE, 0);
3157         g_free (txt);
3158         g_free (server_name);
3159         server_name = NULL;
3160
3161         /* username: */
3162         gchar *initial_username = modest_account_mgr_get_server_account_username (
3163                 modest_runtime_get_account_mgr(), server_account_name);
3164         
3165         GtkWidget *entry_username = gtk_entry_new ();
3166         if (initial_username)
3167                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3168         /* Dim this if a connection has ever succeeded with this username,
3169          * as per the UI spec: */
3170         const gboolean username_known = 
3171                 modest_account_mgr_get_server_account_username_has_succeeded(
3172                         modest_runtime_get_account_mgr(), server_account_name);
3173         gtk_widget_set_sensitive (entry_username, !username_known);
3174         
3175 #ifdef MODEST_PLATFORM_MAEMO
3176         /* Auto-capitalization is the default, so let's turn it off: */
3177         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3178         
3179         /* Create a size group to be used by all captions.
3180          * Note that HildonCaption does not create a default size group if we do not specify one.
3181          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3182         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3183         
3184         GtkWidget *caption = hildon_caption_new (sizegroup, 
3185                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3186         gtk_widget_show (entry_username);
3187         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3188                 FALSE, FALSE, MODEST_MARGIN_HALF);
3189         gtk_widget_show (caption);
3190 #else 
3191         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3192                             TRUE, FALSE, 0);
3193 #endif /* MODEST_PLATFORM_MAEMO */      
3194                             
3195         /* password: */
3196         GtkWidget *entry_password = gtk_entry_new ();
3197         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3198         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3199         
3200 #ifdef MODEST_PLATFORM_MAEMO
3201         /* Auto-capitalization is the default, so let's turn it off: */
3202         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3203                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3204         
3205         caption = hildon_caption_new (sizegroup, 
3206                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3207         gtk_widget_show (entry_password);
3208         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3209                 FALSE, FALSE, MODEST_MARGIN_HALF);
3210         gtk_widget_show (caption);
3211         g_object_unref (sizegroup);
3212 #else 
3213         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3214                             TRUE, FALSE, 0);
3215 #endif /* MODEST_PLATFORM_MAEMO */      
3216
3217         if (initial_username != NULL)
3218                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3219                                 
3220 /* This is not in the Maemo UI spec:
3221         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3222         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3223                             TRUE, FALSE, 0);
3224 */
3225
3226         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3227
3228         while (!completed) {
3229         
3230                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3231                         if (username) {
3232                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3233                                 
3234                                 /* Note that an empty field becomes the "" string */
3235                                 if (*username && strlen (*username) > 0) {
3236                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3237                                                                                         server_account_name, 
3238                                                                                         *username);
3239                                         completed = TRUE;
3240                                 
3241                                         const gboolean username_was_changed = 
3242                                                 (strcmp (*username, initial_username) != 0);
3243                                         if (username_was_changed) {
3244                                                 g_warning ("%s: tinymail does not yet support changing the "
3245                                                            "username in the get_password() callback.\n", __FUNCTION__);
3246                                         }
3247                                 } else {
3248                                         /* Show error */
3249                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3250                                                                             _("mcen_ib_username_pw_incorrect"));
3251                                         completed = FALSE;
3252                                 }
3253                         }
3254                         
3255                         if (password) {
3256                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3257                         
3258                                 /* We do not save the password in the configuration, 
3259                                  * because this function is only called for passwords that should 
3260                                  * not be remembered:
3261                                  modest_server_account_set_password (
3262                                  modest_runtime_get_account_mgr(), server_account_name, 
3263                                  *password);
3264                                  */
3265                         }                       
3266                         if (cancel)
3267                                 *cancel   = FALSE;                      
3268                 } else {
3269                         modest_platform_information_banner(GTK_WIDGET (dialog), 
3270                                                            NULL, _("mail_ib_login_cancelled"));
3271                         completed = TRUE;
3272                         if (username)
3273                                 *username = NULL;                       
3274                         if (password)
3275                                 *password = NULL;                       
3276                         if (cancel)
3277                                 *cancel   = TRUE;
3278                 }
3279         }
3280
3281 /* This is not in the Maemo UI spec:
3282         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3283                 *remember = TRUE;
3284         else
3285                 *remember = FALSE;
3286 */
3287
3288         gtk_widget_destroy (dialog);
3289         
3290         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3291 }
3292
3293 void
3294 modest_ui_actions_on_cut (GtkAction *action,
3295                           ModestWindow *window)
3296 {
3297         GtkWidget *focused_widget;
3298         GtkClipboard *clipboard;
3299
3300         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3301         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3302         if (GTK_IS_EDITABLE (focused_widget)) {
3303                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3304                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3305                 gtk_clipboard_store (clipboard);
3306         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3307                 GtkTextBuffer *buffer;
3308
3309                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3310                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3311                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3312                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3313                         gtk_clipboard_store (clipboard);
3314                 }
3315         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3316                 TnyList *header_list = modest_header_view_get_selected_headers (
3317                                 MODEST_HEADER_VIEW (focused_widget));
3318                 gboolean continue_download = FALSE;
3319                 gint num_of_unc_msgs;
3320
3321                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3322
3323                 if (num_of_unc_msgs) {
3324                         TnyAccount *account = get_account_from_header_list (header_list);
3325                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3326                         g_object_unref (account);
3327                 }
3328
3329                 if (num_of_unc_msgs == 0 || continue_download) {
3330 /*                      modest_platform_information_banner (
3331                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3332                         modest_header_view_cut_selection (
3333                                         MODEST_HEADER_VIEW (focused_widget));
3334                 }
3335
3336                 g_object_unref (header_list);
3337         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3338                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3339         }
3340 }
3341
3342 void
3343 modest_ui_actions_on_copy (GtkAction *action,
3344                            ModestWindow *window)
3345 {
3346         GtkClipboard *clipboard;
3347         GtkWidget *focused_widget;
3348         gboolean copied = TRUE;
3349
3350         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3351         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3352
3353         if (GTK_IS_LABEL (focused_widget)) {
3354                 gchar *selection;
3355                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3356                 gtk_clipboard_set_text (clipboard, selection, -1);
3357                 g_free (selection);
3358                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3359                 gtk_clipboard_store (clipboard);
3360         } else if (GTK_IS_EDITABLE (focused_widget)) {
3361                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3362                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3363                 gtk_clipboard_store (clipboard);
3364         } else if (GTK_IS_HTML (focused_widget)) {
3365                 gtk_html_copy (GTK_HTML (focused_widget));
3366                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3367                 gtk_clipboard_store (clipboard);
3368         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3369                 GtkTextBuffer *buffer;
3370                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3371                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3372                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3373                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3374                         gtk_clipboard_store (clipboard);
3375                 }
3376         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3377                 TnyList *header_list = modest_header_view_get_selected_headers (
3378                                 MODEST_HEADER_VIEW (focused_widget));
3379                 gboolean continue_download = FALSE;
3380                 gint num_of_unc_msgs;
3381
3382                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3383
3384                 if (num_of_unc_msgs) {
3385                         TnyAccount *account = get_account_from_header_list (header_list);
3386                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3387                         g_object_unref (account);
3388                 }
3389
3390                 if (num_of_unc_msgs == 0 || continue_download) {
3391                         modest_platform_information_banner (
3392                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3393                         modest_header_view_copy_selection (
3394                                         MODEST_HEADER_VIEW (focused_widget));
3395                 } else
3396                         copied = FALSE;
3397
3398                 g_object_unref (header_list);
3399
3400         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3401                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3402         }
3403
3404         /* Show information banner if there was a copy to clipboard */
3405         if(copied)
3406                 modest_platform_information_banner (
3407                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3408 }
3409
3410 void
3411 modest_ui_actions_on_undo (GtkAction *action,
3412                            ModestWindow *window)
3413 {
3414         ModestEmailClipboard *clipboard = NULL;
3415
3416         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3417                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3418         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3419                 /* Clear clipboard source */
3420                 clipboard = modest_runtime_get_email_clipboard ();
3421                 modest_email_clipboard_clear (clipboard);               
3422         }
3423         else {
3424                 g_return_if_reached ();
3425         }
3426 }
3427
3428 void
3429 modest_ui_actions_on_redo (GtkAction *action,
3430                            ModestWindow *window)
3431 {
3432         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3433                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3434         }
3435         else {
3436                 g_return_if_reached ();
3437         }
3438 }
3439
3440
3441 static void
3442 destroy_information_note (ModestMailOperation *mail_op, 
3443                           gpointer user_data)
3444 {
3445         /* destroy information note */
3446         gtk_widget_destroy (GTK_WIDGET(user_data));
3447 }
3448
3449 static void
3450 destroy_folder_information_note (ModestMailOperation *mail_op, 
3451                                  TnyFolder *new_folder,
3452                                  gpointer user_data)
3453 {
3454         /* destroy information note */
3455         gtk_widget_destroy (GTK_WIDGET(user_data));
3456 }
3457
3458
3459 static void
3460 paste_as_attachment_free (gpointer data)
3461 {
3462         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3463
3464         gtk_widget_destroy (helper->banner);
3465         g_object_unref (helper->banner);
3466         g_free (helper);
3467 }
3468
3469 static void
3470 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3471                             TnyHeader *header,
3472                             TnyMsg *msg,
3473                             gpointer userdata)
3474 {
3475         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3476         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3477
3478         if (msg == NULL)
3479                 return;
3480
3481         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3482         
3483 }
3484
3485 void
3486 modest_ui_actions_on_paste (GtkAction *action,
3487                             ModestWindow *window)
3488 {
3489         GtkWidget *focused_widget = NULL;
3490         GtkWidget *inf_note = NULL;
3491         ModestMailOperation *mail_op = NULL;
3492
3493         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3494         if (GTK_IS_EDITABLE (focused_widget)) {
3495                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3496         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3497                 ModestEmailClipboard *e_clipboard = NULL;
3498                 e_clipboard = modest_runtime_get_email_clipboard ();
3499                 if (modest_email_clipboard_cleared (e_clipboard)) {
3500                         GtkTextBuffer *buffer;
3501                         GtkClipboard *clipboard;
3502
3503                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3504                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3505                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3506                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3507                         ModestMailOperation *mail_op;
3508                         TnyFolder *src_folder;
3509                         TnyList *data;
3510                         gboolean delete;
3511                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3512                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3513                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3514                                                                            _CS("ckct_nw_pasting"));
3515                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3516                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3517                         if (helper->banner != NULL) {
3518                                 g_object_ref (G_OBJECT (helper->banner));
3519                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3520                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3521                         }
3522
3523                         if (data != NULL) {
3524                                 modest_mail_operation_get_msgs_full (mail_op, 
3525                                                                      data,
3526                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3527                                                                      helper,
3528                                                                      paste_as_attachment_free);
3529                         }
3530                 }
3531         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3532                 ModestEmailClipboard *clipboard = NULL;
3533                 TnyFolder *src_folder = NULL;
3534                 TnyFolderStore *folder_store = NULL;
3535                 TnyList *data = NULL;           
3536                 gboolean delete = FALSE;
3537                 
3538                 /* Check clipboard source */
3539                 clipboard = modest_runtime_get_email_clipboard ();
3540                 if (modest_email_clipboard_cleared (clipboard)) 
3541                         return;
3542                 
3543                 /* Get elements to paste */
3544                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3545
3546                 /* Create a new mail operation */
3547                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3548                 
3549                 /* Get destination folder */
3550                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3551
3552                 /* transfer messages  */
3553                 if (data != NULL) {
3554                         gint response = 0;
3555
3556                         /* Ask for user confirmation */
3557                         response = 
3558                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3559                                                                              TNY_FOLDER (folder_store), 
3560                                                                              delete,
3561                                                                              data);
3562                         
3563                         if (response == GTK_RESPONSE_OK) {
3564                                 /* Launch notification */
3565                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3566                                                                              _CS("ckct_nw_pasting"));
3567                                 if (inf_note != NULL)  {
3568                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3569                                         gtk_widget_show (GTK_WIDGET(inf_note));
3570                                 }
3571
3572                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3573                                 modest_mail_operation_xfer_msgs (mail_op, 
3574                                                                  data,
3575                                                                  TNY_FOLDER (folder_store),
3576                                                                  delete,
3577                                                                  destroy_information_note,
3578                                                                  inf_note);                             
3579                         } else {
3580                                 g_object_unref (mail_op);
3581                         }
3582                         
3583                 } else if (src_folder != NULL) {                        
3584                         /* Launch notification */
3585                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3586                                                                      _CS("ckct_nw_pasting"));
3587                         if (inf_note != NULL)  {
3588                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3589                                 gtk_widget_show (GTK_WIDGET(inf_note));
3590                         }
3591                         
3592                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3593                         modest_mail_operation_xfer_folder (mail_op, 
3594                                                            src_folder,
3595                                                            folder_store,
3596                                                            delete,
3597                                                            destroy_folder_information_note,
3598                                                            inf_note);
3599                 }
3600
3601                 /* Free */
3602                 if (data != NULL) 
3603                         g_object_unref (data);
3604                 if (src_folder != NULL) 
3605                         g_object_unref (src_folder);
3606                 if (folder_store != NULL) 
3607                         g_object_unref (folder_store);
3608         }
3609 }
3610
3611
3612 void
3613 modest_ui_actions_on_select_all (GtkAction *action,
3614                                  ModestWindow *window)
3615 {
3616         GtkWidget *focused_widget;
3617
3618         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3619         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3620                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3621         } else if (GTK_IS_LABEL (focused_widget)) {
3622                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3623         } else if (GTK_IS_EDITABLE (focused_widget)) {
3624                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3625         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3626                 GtkTextBuffer *buffer;
3627                 GtkTextIter start, end;
3628
3629                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3630                 gtk_text_buffer_get_start_iter (buffer, &start);
3631                 gtk_text_buffer_get_end_iter (buffer, &end);
3632                 gtk_text_buffer_select_range (buffer, &start, &end);
3633         } else if (GTK_IS_HTML (focused_widget)) {
3634                 gtk_html_select_all (GTK_HTML (focused_widget));
3635         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3636                 GtkWidget *header_view = focused_widget;
3637                 GtkTreeSelection *selection = NULL;
3638                 
3639                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3640                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3641                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3642                 }
3643                                 
3644                 /* Disable window dimming management */
3645                 modest_window_disable_dimming (MODEST_WINDOW(window));
3646                 
3647                 /* Select all messages */
3648                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3649                 gtk_tree_selection_select_all (selection);
3650
3651                 /* Set focuse on header view */
3652                 gtk_widget_grab_focus (header_view);
3653
3654
3655                 /* Enable window dimming management */
3656                 modest_window_enable_dimming (MODEST_WINDOW(window));
3657                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3658         }
3659
3660 }
3661
3662 void
3663 modest_ui_actions_on_mark_as_read (GtkAction *action,
3664                                    ModestWindow *window)
3665 {       
3666         g_return_if_fail (MODEST_IS_WINDOW(window));
3667                 
3668         /* Mark each header as read */
3669         do_headers_action (window, headers_action_mark_as_read, NULL);
3670 }
3671
3672 void
3673 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3674                                      ModestWindow *window)
3675 {       
3676         g_return_if_fail (MODEST_IS_WINDOW(window));
3677                 
3678         /* Mark each header as read */
3679         do_headers_action (window, headers_action_mark_as_unread, NULL);
3680 }
3681
3682 void
3683 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3684                                   GtkRadioAction *selected,
3685                                   ModestWindow *window)
3686 {
3687         gint value;
3688
3689         value = gtk_radio_action_get_current_value (selected);
3690         if (MODEST_IS_WINDOW (window)) {
3691                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3692         }
3693 }
3694
3695 void
3696 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3697                                                GtkRadioAction *selected,
3698                                                ModestWindow *window)
3699 {
3700         TnyHeaderFlags flags;
3701         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3702
3703         flags = gtk_radio_action_get_current_value (selected);
3704         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3705 }
3706
3707 void
3708 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3709                                                   GtkRadioAction *selected,
3710                                                   ModestWindow *window)
3711 {
3712         gint file_format;
3713
3714         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3715
3716         file_format = gtk_radio_action_get_current_value (selected);
3717         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3718 }
3719
3720
3721 void
3722 modest_ui_actions_on_zoom_plus (GtkAction *action,
3723                                 ModestWindow *window)
3724 {
3725         g_return_if_fail (MODEST_IS_WINDOW (window));
3726
3727         modest_window_zoom_plus (MODEST_WINDOW (window));
3728 }
3729
3730 void     
3731 modest_ui_actions_on_zoom_minus (GtkAction *action,
3732                                  ModestWindow *window)
3733 {
3734         g_return_if_fail (MODEST_IS_WINDOW (window));
3735
3736         modest_window_zoom_minus (MODEST_WINDOW (window));
3737 }
3738
3739 void     
3740 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3741                                            ModestWindow *window)
3742 {
3743         ModestWindowMgr *mgr;
3744         gboolean fullscreen, active;
3745         g_return_if_fail (MODEST_IS_WINDOW (window));
3746
3747         mgr = modest_runtime_get_window_mgr ();
3748
3749         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3750         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3751
3752         if (active != fullscreen) {
3753                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3754                 gtk_window_present (GTK_WINDOW (window));
3755         }
3756 }
3757
3758 void
3759 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3760                                         ModestWindow *window)
3761 {
3762         ModestWindowMgr *mgr;
3763         gboolean fullscreen;
3764
3765         g_return_if_fail (MODEST_IS_WINDOW (window));
3766
3767         mgr = modest_runtime_get_window_mgr ();
3768         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3769         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3770
3771         gtk_window_present (GTK_WINDOW (window));
3772 }
3773
3774 /* 
3775  * Used by modest_ui_actions_on_details to call do_headers_action 
3776  */
3777 static void
3778 headers_action_show_details (TnyHeader *header, 
3779                              ModestWindow *window,
3780                              gpointer user_data)
3781
3782 {
3783         GtkWidget *dialog;
3784         
3785         /* Create dialog */
3786         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3787
3788         /* Run dialog */
3789         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3790         gtk_widget_show_all (dialog);
3791         gtk_dialog_run (GTK_DIALOG (dialog));
3792
3793         gtk_widget_destroy (dialog);
3794 }
3795
3796 /*
3797  * Show the folder details in a ModestDetailsDialog widget
3798  */
3799 static void
3800 show_folder_details (TnyFolder *folder, 
3801                      GtkWindow *window)
3802 {
3803         GtkWidget *dialog;
3804         
3805         /* Create dialog */
3806         dialog = modest_details_dialog_new_with_folder (window, folder);
3807
3808         /* Run dialog */
3809         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3810         gtk_widget_show_all (dialog);
3811         gtk_dialog_run (GTK_DIALOG (dialog));
3812
3813         gtk_widget_destroy (dialog);
3814 }
3815
3816 /*
3817  * Show the header details in a ModestDetailsDialog widget
3818  */
3819 void     
3820 modest_ui_actions_on_details (GtkAction *action, 
3821                               ModestWindow *win)
3822 {
3823         TnyList * headers_list;
3824         TnyIterator *iter;
3825         TnyHeader *header;              
3826
3827         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3828                 TnyMsg *msg;
3829
3830                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3831                 if (!msg)
3832                         return;
3833                 g_object_unref (msg);           
3834
3835                 headers_list = get_selected_headers (win);
3836                 if (!headers_list)
3837                         return;
3838
3839                 iter = tny_list_create_iterator (headers_list);
3840
3841                 header = TNY_HEADER (tny_iterator_get_current (iter));
3842                 if (header) {
3843                         headers_action_show_details (header, win, NULL);
3844                         g_object_unref (header);
3845                 }
3846
3847                 g_object_unref (iter);
3848                 g_object_unref (headers_list);
3849
3850         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3851                 GtkWidget *folder_view, *header_view;
3852
3853                 /* Check which widget has the focus */
3854                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3855                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3856                 if (gtk_widget_is_focus (folder_view)) {
3857                         TnyFolderStore *folder_store
3858                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3859                         if (!folder_store) {
3860                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3861                                 return; 
3862                         }
3863                         /* Show only when it's a folder */
3864                         /* This function should not be called for account items, 
3865                          * because we dim the menu item for them. */
3866                         if (TNY_IS_FOLDER (folder_store)) {
3867                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3868                         }
3869
3870                         g_object_unref (folder_store);
3871
3872                 } else {
3873                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3874                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3875                         /* Show details of each header */
3876                         do_headers_action (win, headers_action_show_details, header_view);
3877                 }
3878         }
3879 }
3880
3881 void     
3882 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3883                                      ModestMsgEditWindow *window)
3884 {
3885         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3886
3887         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3888 }
3889
3890 void     
3891 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3892                                       ModestMsgEditWindow *window)
3893 {
3894         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3895
3896         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3897 }
3898
3899 void
3900 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3901                                        ModestMainWindow *main_window)
3902 {
3903         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3904
3905         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3906                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3907         else
3908                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3909 }
3910
3911 void 
3912 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3913                                      ModestWindow *window)
3914 {
3915         gboolean active, fullscreen = FALSE;
3916         ModestWindowMgr *mgr;
3917
3918         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3919
3920         /* Check if we want to toggle the toolbar vuew in fullscreen
3921            or normal mode */
3922         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3923                      "ViewShowToolbarFullScreen")) {
3924                 fullscreen = TRUE;
3925         }
3926
3927         /* Toggle toolbar */
3928         mgr = modest_runtime_get_window_mgr ();
3929         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3930 }
3931
3932 void     
3933 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3934                                            ModestMsgEditWindow *window)
3935 {
3936         modest_msg_edit_window_select_font (window);
3937 }
3938
3939
3940 void
3941 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3942                                                   const gchar *display_name,
3943                                                   GtkWindow *window)
3944 {
3945         /* don't update the display name if it was already set;
3946          * updating the display name apparently is expensive */
3947         const gchar* old_name = gtk_window_get_title (window);
3948
3949         if (display_name == NULL)
3950                 display_name = " ";
3951
3952         if (old_name && display_name && strcmp (old_name, display_name) == 0)
3953                 return; /* don't do anything */
3954
3955         /* This is usually used to change the title of the main window, which
3956          * is the one that holds the folder view. Note that this change can
3957          * happen even when the widget doesn't have the focus. */
3958         gtk_window_set_title (window, display_name);
3959
3960 }
3961
3962 void
3963 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3964 {
3965         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3966         modest_msg_edit_window_select_contacts (window);
3967 }
3968
3969 void
3970 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3971 {
3972         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3973         modest_msg_edit_window_check_names (window, FALSE);
3974 }
3975
3976 static void
3977 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3978 {
3979         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3980                                          GTK_WIDGET (user_data));
3981 }
3982
3983 /*
3984  * This function is used to track changes in the selection of the
3985  * folder view that is inside the "move to" dialog to enable/disable
3986  * the OK button because we do not want the user to select a disallowed
3987  * destination for a folder.
3988  * The user also not desired to be able to use NEW button on items where
3989  * folder creation is not possibel.
3990  */
3991 static void
3992 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3993                                             TnyFolderStore *folder_store,
3994                                             gboolean selected,
3995                                             gpointer user_data)
3996 {
3997         GtkWidget *dialog = NULL;
3998         GtkWidget *ok_button = NULL, *new_button = NULL;
3999         GList *children = NULL;
4000         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4001         gboolean moving_folder = FALSE;
4002         gboolean is_local_account = TRUE;
4003         GtkWidget *folder_view = NULL;
4004         ModestTnyFolderRules rules;
4005
4006         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4007         
4008         if (!selected)
4009                 return;
4010         
4011         /* Get the OK button */
4012         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4013         if (!dialog)
4014                 return;
4015
4016         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4017         ok_button = GTK_WIDGET (children->next->next->data);
4018         new_button = GTK_WIDGET (children->next->data);
4019         g_list_free (children);
4020
4021         /* check if folder_store is an remote account */
4022         if (TNY_IS_ACCOUNT (folder_store)) {
4023                 TnyAccount *local_account = NULL;
4024                 TnyAccount *mmc_account = NULL;
4025                 ModestTnyAccountStore *account_store = NULL;
4026
4027                 account_store = modest_runtime_get_account_store ();
4028                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4029                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4030
4031                 if ((gpointer) local_account != (gpointer) folder_store &&
4032                     (gpointer) mmc_account != (gpointer) folder_store) {
4033                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4034                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4035                         if (proto_name != NULL) {
4036                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4037                         }
4038                         is_local_account = FALSE;
4039                         /* New button should be dimmed on remote
4040                            POP account root */
4041                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4042                 }
4043                 g_object_unref (local_account);
4044                 g_object_unref (mmc_account);
4045         }
4046
4047         /* Check the target folder rules */
4048         if (TNY_IS_FOLDER (folder_store)) {
4049                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4050                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4051                         ok_sensitive = FALSE;
4052                         new_sensitive = FALSE;
4053                         goto end;
4054                 }
4055         }
4056
4057         /* Check if we're moving a folder */
4058         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4059                 /* Get the widgets */
4060                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4061                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4062                 if (gtk_widget_is_focus (folder_view))
4063                         moving_folder = TRUE;
4064         }
4065
4066         if (moving_folder) {
4067                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4068
4069                 /* Get the folder to move */
4070                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4071                 
4072                 /* Check that we're not moving to the same folder */
4073                 if (TNY_IS_FOLDER (moved_folder)) {
4074                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4075                         if (parent == folder_store)
4076                                 ok_sensitive = FALSE;
4077                         g_object_unref (parent);
4078                 } 
4079
4080                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4081                         /* Do not allow to move to an account unless it's the
4082                            local folders account */
4083                         if (!is_local_account)
4084                                 ok_sensitive = FALSE;
4085                 } 
4086
4087                 if (ok_sensitive && (moved_folder == folder_store)) {
4088                         /* Do not allow to move to itself */
4089                         ok_sensitive = FALSE;
4090                 }
4091                 g_object_unref (moved_folder);
4092         } else {
4093                 TnyFolder *src_folder = NULL;
4094
4095                 /* Moving a message */
4096                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4097
4098                         TnyHeader *header = NULL;
4099                         header = modest_msg_view_window_get_header
4100                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4101                         if (!TNY_IS_HEADER(header))
4102                                 g_warning ("%s: could not get source header", __FUNCTION__);
4103                         else
4104                                 src_folder = tny_header_get_folder (header);
4105
4106                         if (header)
4107                                 g_object_unref (header);
4108                 } else {
4109                         src_folder = 
4110                                 TNY_FOLDER (modest_folder_view_get_selected
4111                                             (MODEST_FOLDER_VIEW (folder_view)));
4112                 }
4113
4114                 if (TNY_IS_FOLDER(src_folder)) {
4115                         /* Do not allow to move the msg to the same folder */
4116                         /* Do not allow to move the msg to an account */
4117                         if ((gpointer) src_folder == (gpointer) folder_store ||
4118                             TNY_IS_ACCOUNT (folder_store))
4119                                 ok_sensitive = FALSE;
4120                         g_object_unref (src_folder);
4121                 } else
4122                         g_warning ("%s: could not get source folder", __FUNCTION__);
4123         }
4124
4125  end:
4126         /* Set sensitivity of the OK button */
4127         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4128         /* Set sensitivity of the NEW button */
4129         gtk_widget_set_sensitive (new_button, new_sensitive);
4130 }
4131
4132
4133 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4134
4135 static GtkWidget*
4136 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4137 {
4138         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4139                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4140 }
4141
4142 static GtkWidget*
4143 create_move_to_dialog (GtkWindow *win,
4144                        GtkWidget *folder_view,
4145                        GtkWidget **tree_view)
4146 {
4147         GtkWidget *dialog, *scroll;
4148         GtkWidget *new_button;
4149
4150         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4151                                               GTK_WINDOW (win),
4152                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4153                                               NULL);
4154
4155         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4156         /* We do this manually so GTK+ does not associate a response ID for
4157          * the button. */
4158         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4159         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4160         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4161
4162         /* Create scrolled window */
4163         scroll = gtk_scrolled_window_new (NULL, NULL);
4164         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4165                                          GTK_POLICY_AUTOMATIC,
4166                                          GTK_POLICY_AUTOMATIC);
4167
4168         /* Create folder view */
4169         *tree_view = modest_platform_create_folder_view (NULL);
4170
4171         /* Track changes in the selection to
4172          * disable the OK button whenever "Move to" is not possible
4173          * disbale NEW button whenever New is not possible */
4174         g_signal_connect (*tree_view,
4175                           "folder_selection_changed",
4176                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4177                           win);
4178
4179         /* Listen to clicks on New button */
4180         g_signal_connect (G_OBJECT (new_button), 
4181                           "clicked", 
4182                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4183                           *tree_view);
4184
4185         /* It could happen that we're trying to move a message from a
4186            window (msg window for example) after the main window was
4187            closed, so we can not just get the model of the folder
4188            view */
4189         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4190                 const gchar *visible_id = NULL;
4191
4192                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4193                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4194                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4195                                                MODEST_FOLDER_VIEW(*tree_view));
4196
4197                 visible_id = 
4198                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4199
4200                 /* Show the same account than the one that is shown in the main window */
4201                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4202                                                                              visible_id);
4203         } else {
4204                 const gchar *active_account_name = NULL;
4205                 ModestAccountMgr *mgr = NULL;
4206                 ModestAccountSettings *settings = NULL;
4207                 ModestServerAccountSettings *store_settings = NULL;
4208
4209                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4210                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4211                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4212                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4213
4214                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4215                 mgr = modest_runtime_get_account_mgr ();
4216                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4217
4218                 if (settings) {
4219                         const gchar *store_account_name;
4220                         store_settings = modest_account_settings_get_store_settings (settings);
4221                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4222
4223                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4224                                                                                      store_account_name);
4225                         g_object_unref (store_settings);
4226                         g_object_unref (settings);
4227                 }
4228         }
4229
4230         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4231          *   get_folder_view_from_move_to_dialog 
4232          * (see above) later (needed for focus handling) 
4233          */
4234         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4235
4236         
4237         /* Hide special folders */
4238         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4239
4240         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4241
4242         /* Add scroll to dialog */
4243         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4244                             scroll, TRUE, TRUE, 0);
4245
4246         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4247         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4248
4249         return dialog;
4250 }
4251
4252 /*
4253  * Returns TRUE if at least one of the headers of the list belongs to
4254  * a message that has been fully retrieved.
4255  */
4256 #if 0 /* no longer in use. delete in 2007.10 */
4257 static gboolean
4258 has_retrieved_msgs (TnyList *list)
4259 {
4260         TnyIterator *iter;
4261         gboolean found = FALSE;
4262
4263         iter = tny_list_create_iterator (list);
4264         while (!tny_iterator_is_done (iter) && !found) {
4265                 TnyHeader *header;
4266                 TnyHeaderFlags flags = 0;
4267
4268                 header = TNY_HEADER (tny_iterator_get_current (iter));
4269                 if (header) {
4270                         flags = tny_header_get_flags (header);
4271                         if (flags & TNY_HEADER_FLAG_CACHED)
4272 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4273                                 found = TRUE;
4274
4275                         g_object_unref (header);
4276                 }
4277
4278                 if (!found)
4279                         tny_iterator_next (iter);
4280         }
4281         g_object_unref (iter);
4282
4283         return found;
4284 }
4285 #endif /* 0 */
4286
4287
4288 /*
4289  * Shows a confirmation dialog to the user when we're moving messages
4290  * from a remote server to the local storage. Returns the dialog
4291  * response. If it's other kind of movement then it always returns
4292  * GTK_RESPONSE_OK
4293  *
4294  * This one is used by the next functions:
4295  *      modest_ui_actions_on_paste                      - commented out
4296  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4297  */
4298 gint
4299 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4300                                              TnyFolder *dest_folder,
4301                                              gboolean delete,
4302                                              TnyList *headers)
4303 {
4304         gint response = GTK_RESPONSE_OK;
4305         TnyAccount *account = NULL;
4306         TnyFolder *src_folder = NULL;
4307         TnyIterator *iter = NULL;
4308         TnyHeader *header = NULL;
4309
4310         /* return with OK if the destination is a remote folder */
4311         if (modest_tny_folder_is_remote_folder (dest_folder))
4312                 return GTK_RESPONSE_OK;
4313
4314         /* Get source folder */
4315         iter = tny_list_create_iterator (headers);
4316         header = TNY_HEADER (tny_iterator_get_current (iter));
4317         if (header) {
4318                 src_folder = tny_header_get_folder (header);
4319                 g_object_unref (header);
4320         }
4321         g_object_unref (iter);
4322
4323         /* if no src_folder, message may be an attahcment */
4324         if (src_folder == NULL) 
4325                 return GTK_RESPONSE_CANCEL;
4326
4327         /* If the source is a local or MMC folder */
4328         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4329                 g_object_unref (src_folder);
4330                 return GTK_RESPONSE_OK;
4331         }
4332
4333         /* Get the account */
4334         account = tny_folder_get_account (src_folder);
4335
4336         /* now if offline we ask the user */
4337         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4338                 response = GTK_RESPONSE_OK;
4339         else
4340                 response = GTK_RESPONSE_CANCEL;
4341
4342         /* Frees */
4343         g_object_unref (src_folder);
4344         g_object_unref (account);
4345
4346         return response;
4347 }
4348
4349 static void
4350 move_to_cb (ModestMailOperation *mail_op, 
4351             gpointer user_data)
4352 {
4353         MoveToHelper *helper = (MoveToHelper *) user_data;
4354
4355         /* Note that the operation could have failed, in that case do
4356            nothing */
4357         if (modest_mail_operation_get_status (mail_op) == 
4358             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4359
4360                 GObject *object = modest_mail_operation_get_source (mail_op);
4361                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4362                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4363
4364                         if (!modest_msg_view_window_select_next_message (self) &&
4365                             !modest_msg_view_window_select_previous_message (self)) {
4366                                 /* No more messages to view, so close this window */
4367                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4368                         }
4369                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4370                         GtkWidget *header_view;
4371                         GtkTreePath *path;
4372                         GtkTreeSelection *sel;
4373
4374                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4375                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4376                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4377                         path = gtk_tree_row_reference_get_path (helper->reference);
4378                         gtk_tree_selection_select_path (sel, path);
4379                         gtk_tree_path_free (path);
4380                 }
4381                 g_object_unref (object);
4382         }
4383
4384         /* Close the "Pasting" information banner */
4385         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4386         if (helper->reference != NULL)
4387                 gtk_tree_row_reference_free (helper->reference);
4388         g_free (helper);
4389 }
4390
4391 static void
4392 folder_move_to_cb (ModestMailOperation *mail_op, 
4393                    TnyFolder *new_folder,
4394                    gpointer user_data)
4395 {
4396         GtkWidget *folder_view;
4397         GObject *object;
4398
4399         object = modest_mail_operation_get_source (mail_op);
4400         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4401                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4402         g_object_ref (folder_view);
4403         g_object_unref (object);
4404         move_to_cb (mail_op, user_data);
4405         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4406         g_object_unref (folder_view);
4407 }
4408
4409 static void
4410 msgs_move_to_cb (ModestMailOperation *mail_op, 
4411                  gpointer user_data)
4412 {
4413         move_to_cb (mail_op, user_data);
4414 }
4415
4416 void
4417 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4418                                              gpointer user_data)
4419 {
4420         ModestWindow *main_window = NULL;
4421         GObject *win = NULL;
4422         
4423         /* Disable next automatic folder selection */
4424         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4425                                                          FALSE); /* don't create */
4426         if (main_window) {
4427                 GtkWidget *folder_view = NULL;
4428         
4429                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4430                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4431                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4432                 
4433                 if (user_data && TNY_IS_FOLDER (user_data)) {
4434                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4435                                                           TNY_FOLDER (user_data), FALSE);
4436                 }
4437         }
4438
4439         /* Show notification dialog */
4440         win = modest_mail_operation_get_source (mail_op);
4441         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4442         if (win)
4443                 g_object_unref (win);
4444 }
4445
4446 void
4447 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4448                                               gpointer user_data)
4449 {
4450         GObject *win = modest_mail_operation_get_source (mail_op);
4451         const GError *error = modest_mail_operation_get_error (mail_op);
4452
4453         g_return_if_fail (error != NULL);
4454         if (error->message != NULL)             
4455                 g_printerr ("modest: %s\n", error->message);
4456         else
4457                 g_printerr ("modest: unkonw error on send&receive operation");
4458
4459         /* Show error message */
4460 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4461 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4462 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4463 /*      else  */
4464 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4465 /*                                                      _CS("sfil_ib_unable_to_send")); */
4466         g_object_unref (win);
4467 }
4468
4469 static void
4470 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4471                        TnyHeader *header, 
4472                        gboolean canceled,
4473                        TnyMsg *msg, 
4474                        GError *err,
4475                        gpointer user_data)
4476 {
4477         TnyList *parts;
4478         TnyIterator *iter;
4479         gint pending_purges = 0;
4480         gboolean some_purged = FALSE;
4481         ModestWindow *win = MODEST_WINDOW (user_data);
4482         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4483
4484         /* If there was any error */
4485         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4486                 modest_window_mgr_unregister_header (mgr, header);
4487                 return;
4488         }
4489
4490         /* Once the message has been retrieved for purging, we check if
4491          * it's all ok for purging */
4492
4493         parts = tny_simple_list_new ();
4494         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4495         iter = tny_list_create_iterator (parts);
4496
4497         while (!tny_iterator_is_done (iter)) {
4498                 TnyMimePart *part;
4499                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4500                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4501                         if (tny_mime_part_is_purged (part))
4502                                 some_purged = TRUE;
4503                         else
4504                                 pending_purges++;
4505                 }
4506
4507                 if (part)
4508                         g_object_unref (part);
4509
4510                 tny_iterator_next (iter);
4511         }
4512         g_object_unref (iter);
4513         
4514
4515         if (pending_purges>0) {
4516                 gint response;
4517                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4518
4519                 if (response == GTK_RESPONSE_OK) {
4520                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4521                         iter = tny_list_create_iterator (parts);
4522                         while (!tny_iterator_is_done (iter)) {
4523                                 TnyMimePart *part;
4524                                 
4525                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4526                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4527                                         tny_mime_part_set_purged (part);
4528
4529                                 if (part)
4530                                         g_object_unref (part);
4531
4532                                 tny_iterator_next (iter);
4533                         }
4534                         g_object_unref (iter);
4535                         
4536                         tny_msg_rewrite_cache (msg);
4537                 }
4538      /* } else { */
4539                 /* This string no longer exists, refer to NB#75415 for more info */
4540                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4541         }
4542
4543         modest_window_mgr_unregister_header (mgr, header);
4544
4545         g_object_unref (parts);
4546 }
4547
4548 static void
4549 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4550                                                      ModestMainWindow *win)
4551 {
4552         GtkWidget *header_view;
4553         TnyList *header_list;
4554         TnyHeader *header;
4555         TnyHeaderFlags flags;
4556         ModestWindow *msg_view_window =  NULL;
4557         gboolean found;
4558
4559         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4560
4561         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4562                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4563
4564         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4565         if (!header_list) {
4566                 g_warning ("%s: no header selected", __FUNCTION__);
4567                 return;
4568         }
4569         
4570         if (tny_list_get_length (header_list) == 1) {
4571                 TnyIterator *iter = tny_list_create_iterator (header_list);
4572                 header = TNY_HEADER (tny_iterator_get_current (iter));
4573                 g_object_unref (iter);
4574         } else
4575                 return;
4576         
4577         if (!header || !TNY_IS_HEADER(header)) {
4578                 g_warning ("%s: header is not valid", __FUNCTION__);
4579                 return;
4580         }
4581         
4582         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4583                                                           header, &msg_view_window);
4584         flags = tny_header_get_flags (header);
4585         if (!(flags & TNY_HEADER_FLAG_CACHED))
4586                 return;
4587         if (found) {
4588                 if (msg_view_window != NULL) 
4589                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4590                 else {
4591                         /* do nothing; uid was registered before, so window is probably on it's way */
4592                         g_warning ("debug: header %p has already been registered", header);
4593                 }
4594         } else {
4595                 ModestMailOperation *mail_op = NULL;
4596                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4597                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4598                                                                          modest_ui_actions_get_msgs_full_error_handler,
4599                                                                          NULL, NULL);
4600                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4601                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4602                 
4603                 g_object_unref (mail_op);
4604         }
4605         if (header)
4606                 g_object_unref (header);
4607         if (header_list)
4608                 g_object_unref (header_list);
4609 }
4610
4611 /*
4612  * Checks if we need a connection to do the transfer and if the user
4613  * wants to connect to complete it
4614  */
4615 void
4616 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4617                                        TnyFolderStore *src_folder,
4618                                        TnyList *headers,
4619                                        TnyFolder *dst_folder,
4620                                        gboolean delete_originals,
4621                                        gboolean *need_connection,
4622                                        gboolean *do_xfer)
4623 {
4624         TnyAccount *src_account;
4625         gint uncached_msgs = 0;
4626
4627         uncached_msgs = header_list_count_uncached_msgs (headers);
4628
4629         /* We don't need any further check if
4630          *
4631          * 1- the source folder is local OR
4632          * 2- the device is already online
4633          */
4634         if (!modest_tny_folder_store_is_remote (src_folder) ||
4635             tny_device_is_online (modest_runtime_get_device())) {
4636                 *need_connection = FALSE;
4637                 *do_xfer = TRUE;
4638                 return;
4639         }
4640
4641         /* We must ask for a connection when
4642          *
4643          *   - the message(s) is not already cached   OR 
4644          *   - the message(s) is cached but the leave_on_server setting
4645          * is FALSE (because we need to sync the source folder to
4646          * delete the message from the server (for IMAP we could do it
4647          * offline, it'll take place the next time we get a
4648          * connection)
4649          */
4650         src_account = get_account_from_folder_store (src_folder);
4651         if (uncached_msgs > 0) {
4652                 guint num_headers;
4653                 const gchar *msg;
4654
4655                 *need_connection = TRUE;
4656                 num_headers = tny_list_get_length (headers);
4657                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4658
4659                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4660                     GTK_RESPONSE_CANCEL) {
4661                         *do_xfer = FALSE;
4662                 } else {
4663                         *do_xfer = TRUE;
4664                 }
4665         } else {
4666                 /* The transfer is possible and the user wants to */
4667                 *do_xfer = TRUE;
4668
4669                 if (remote_folder_is_pop (src_folder) && delete_originals) {
4670                         const gchar *account_name;
4671                         gboolean leave_on_server;
4672                         
4673                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4674                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4675                                                                                   account_name);
4676                         
4677                         if (leave_on_server == TRUE) {
4678                                 *need_connection = FALSE;
4679                         } else {
4680                                 *need_connection = TRUE;
4681                         }
4682                 } else {
4683                         *need_connection = FALSE;
4684                 }
4685         }
4686
4687         /* Frees */
4688         g_object_unref (src_account);
4689 }
4690
4691
4692 /**
4693  * Utility function that transfer messages from both the main window
4694  * and the msg view window when using the "Move to" dialog
4695  */
4696 static void
4697 xfer_messages_performer  (gboolean canceled, 
4698                           GError *err,
4699                           GtkWindow *parent_window, 
4700                           TnyAccount *account, 
4701                           gpointer user_data)
4702 {
4703         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4704         ModestWindow *win = MODEST_WINDOW (parent_window);
4705         TnyList *headers = NULL;
4706         TnyAccount *dst_account = NULL;
4707         const gchar *proto_str = NULL;
4708         gboolean dst_is_pop = FALSE;
4709
4710         if (canceled || err) {
4711                 /* Show the proper error message */
4712                 modest_ui_actions_on_account_connection_error (parent_window, account);
4713                 g_object_unref (dst_folder);
4714                 return;
4715         }
4716
4717         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4718         proto_str = tny_account_get_proto (dst_account);
4719
4720         /* tinymail will return NULL for local folders it seems */
4721         dst_is_pop = proto_str &&
4722                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4723                  MODEST_PROTOCOL_STORE_POP);
4724
4725         g_object_unref (dst_account);
4726
4727         /* Get selected headers */
4728         headers = get_selected_headers (MODEST_WINDOW (win));
4729         if (!headers) {
4730                 g_warning ("%s: no headers selected", __FUNCTION__);
4731                 return;
4732         }
4733
4734
4735         if (dst_is_pop) {
4736                 modest_platform_information_banner (GTK_WIDGET (win),
4737                                                     NULL,
4738                                                     ngettext("mail_in_ui_folder_move_target_error",
4739                                                              "mail_in_ui_folder_move_targets_error",
4740                                                              tny_list_get_length (headers)));
4741                 g_object_unref (headers);
4742                 return;
4743         }
4744
4745         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4746         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4747                                                            _CS("ckct_nw_pasting"));
4748         if (helper->banner != NULL)  {
4749                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4750                 gtk_widget_show (GTK_WIDGET(helper->banner));
4751         }
4752
4753         if (MODEST_IS_MAIN_WINDOW (win)) {
4754                 GtkWidget *header_view = 
4755                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4756                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4757                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4758         }
4759
4760         ModestMailOperation *mail_op = 
4761                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4762                                                                modest_ui_actions_move_folder_error_handler,
4763                                                                NULL, NULL);
4764         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4765                                          mail_op);
4766
4767         modest_mail_operation_xfer_msgs (mail_op, 
4768                                          headers,
4769                                          TNY_FOLDER (dst_folder),
4770                                          TRUE,
4771                                          msgs_move_to_cb,
4772                                          helper);
4773
4774         g_object_unref (G_OBJECT (mail_op));
4775         g_object_unref (headers);
4776         g_object_unref (dst_folder);
4777 }
4778
4779 typedef struct {
4780         TnyFolder *src_folder;
4781         TnyFolderStore *dst_folder;
4782         gboolean delete_original;
4783         GtkWidget *folder_view;
4784 } MoveFolderInfo;
4785
4786 static void
4787 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4788                 TnyAccount *account, gpointer user_data)
4789 {
4790         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4791         GtkTreeSelection *sel;
4792         ModestMailOperation *mail_op = NULL;
4793         
4794         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4795                 g_object_unref (G_OBJECT (info->src_folder));
4796                 g_object_unref (G_OBJECT (info->dst_folder));
4797                 g_free (info);
4798                 return;
4799         }
4800         
4801         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4802         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4803                         _CS("ckct_nw_pasting"));
4804         if (helper->banner != NULL)  {
4805                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4806                 gtk_widget_show (GTK_WIDGET(helper->banner));
4807         }
4808         /* Clean folder on header view before moving it */
4809         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4810         gtk_tree_selection_unselect_all (sel);
4811
4812         /* Let gtk events run. We need that the folder
4813            view frees its reference to the source
4814            folder *before* issuing the mail operation
4815            so we need the signal handler of selection
4816            changed to happen before the mail
4817            operation 
4818         while (gtk_events_pending ())
4819                 gtk_main_iteration ();   */
4820
4821         mail_op =
4822                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4823                                 modest_ui_actions_move_folder_error_handler,
4824                                 info->src_folder, NULL);
4825         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4826                         mail_op);
4827
4828         /* Select *after* the changes */
4829         /* TODO: this function hangs UI after transfer */ 
4830         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4831         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4832
4833         modest_mail_operation_xfer_folder (mail_op,
4834                         TNY_FOLDER (info->src_folder),
4835                         info->dst_folder,
4836                         info->delete_original, 
4837                         folder_move_to_cb, 
4838                         helper);
4839
4840         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {       
4841                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4842                                                   TNY_FOLDER (info->dst_folder), TRUE);
4843         }
4844         
4845         /* Unref mail operation */
4846         g_object_unref (G_OBJECT (mail_op));
4847         g_object_unref (G_OBJECT (info->src_folder));
4848         g_object_unref (G_OBJECT (info->dst_folder));
4849         g_free (user_data);
4850 }
4851
4852 static TnyAccount *
4853 get_account_from_folder_store (TnyFolderStore *folder_store) 
4854 {
4855         if (TNY_IS_ACCOUNT (folder_store))
4856                 return g_object_ref (folder_store);
4857         else
4858                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4859 }
4860
4861 /*
4862  * UI handler for the "Move to" action when invoked from the
4863  * ModestMainWindow
4864  */
4865 static void 
4866 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4867                                           GtkWidget *folder_view,
4868                                           TnyFolderStore *dst_folder,
4869                                           ModestMainWindow *win)
4870 {
4871         ModestHeaderView *header_view = NULL;
4872         TnyFolderStore *src_folder = NULL;
4873
4874         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4875
4876         /* Get the source folder */
4877         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4878
4879         /* Get header view */
4880         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4881
4882         /* Get folder or messages to transfer */
4883         if (gtk_widget_is_focus (folder_view)) {
4884                 gboolean do_xfer = TRUE;
4885
4886                 /* Allow only to transfer folders to the local root folder */
4887                 if (TNY_IS_ACCOUNT (dst_folder) && 
4888                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4889                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4890                         do_xfer = FALSE;
4891                 } else if (!TNY_IS_FOLDER (src_folder)) {
4892                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4893                         do_xfer = FALSE;
4894                 }
4895
4896                 if (do_xfer) {                  
4897                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4898                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4899
4900                         info->src_folder = g_object_ref (src_folder);
4901                         info->dst_folder = g_object_ref (dst_folder);
4902                         info->delete_original = TRUE;
4903                         info->folder_view = folder_view;
4904
4905                         connect_info->callback = on_move_folder_cb;
4906                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4907                         connect_info->data = info;
4908
4909                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4910                                                                    TNY_FOLDER_STORE (src_folder), 
4911                                                                    connect_info);
4912                 }
4913         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4914                 TnyList *headers;
4915
4916                 headers = modest_header_view_get_selected_headers(header_view);
4917
4918                 /* Transfer the messages */
4919                 transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
4920                                           headers, TNY_FOLDER (dst_folder));
4921
4922                 g_object_unref (headers);
4923         }
4924
4925         /* Frees */
4926         g_object_unref (src_folder);
4927 }
4928
4929
4930 static void
4931 transfer_messages_helper (GtkWindow *win,
4932                           TnyFolder *src_folder,
4933                           TnyList *headers,
4934                           TnyFolder *dst_folder)
4935 {
4936         gboolean need_connection = TRUE;
4937         gboolean do_xfer = TRUE;
4938         
4939         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
4940                                                headers, TNY_FOLDER (dst_folder),
4941                                                TRUE, &need_connection, 
4942                                                &do_xfer);
4943
4944         /* If we don't want to transfer just return */
4945         if (!do_xfer)
4946                 return;
4947
4948         if (need_connection) {
4949                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4950                 connect_info->callback = xfer_messages_performer;
4951                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4952                 connect_info->data = g_object_ref (dst_folder);
4953                 
4954                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4955                                                            TNY_FOLDER_STORE (src_folder), 
4956                                                            connect_info);
4957         } else {
4958                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
4959                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
4960                                          src_account, 
4961                                          g_object_ref (dst_folder));
4962                 g_object_unref (src_account);
4963         }
4964 }
4965
4966 /*
4967  * UI handler for the "Move to" action when invoked from the
4968  * ModestMsgViewWindow
4969  */
4970 static void 
4971 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4972                                               TnyFolderStore *dst_folder,
4973                                               ModestMsgViewWindow *win)
4974 {
4975         TnyList *headers = NULL;
4976         TnyHeader *header = NULL;
4977         TnyFolder *src_folder = NULL;
4978
4979         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
4980
4981         /* Create header list */
4982         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
4983         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4984         headers = tny_simple_list_new ();
4985         tny_list_append (headers, G_OBJECT (header));
4986
4987         /* Transfer the messages */
4988         transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
4989                                   TNY_FOLDER (dst_folder));
4990
4991         /* Frees */
4992         g_object_unref (header);
4993         g_object_unref (headers);
4994 }
4995
4996 void 
4997 modest_ui_actions_on_move_to (GtkAction *action, 
4998                               ModestWindow *win)
4999 {
5000         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5001         gint result = 0;
5002         TnyFolderStore *dst_folder = NULL;
5003         ModestMainWindow *main_window;
5004
5005         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5006                           MODEST_IS_MSG_VIEW_WINDOW (win));
5007
5008         /* Get the main window if exists */
5009         if (MODEST_IS_MAIN_WINDOW (win))
5010                 main_window = MODEST_MAIN_WINDOW (win);
5011         else
5012                 main_window = 
5013                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5014                                                                                FALSE)); /* don't create */
5015
5016         /* Get the folder view widget if exists */
5017         if (main_window)
5018                 folder_view = modest_main_window_get_child_widget (main_window,
5019                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5020         else
5021                 folder_view = NULL;
5022
5023         /* Create and run the dialog */
5024         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5025         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5026         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5027         result = gtk_dialog_run (GTK_DIALOG(dialog));
5028         g_object_ref (tree_view);
5029         gtk_widget_destroy (dialog);
5030
5031         if (result != GTK_RESPONSE_ACCEPT)
5032                 return;
5033
5034         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5035         /* Do window specific stuff */
5036         if (MODEST_IS_MAIN_WINDOW (win)) {
5037                 modest_ui_actions_on_main_window_move_to (action,
5038                                 folder_view,
5039                                 dst_folder,
5040                                 MODEST_MAIN_WINDOW (win));
5041         } else {
5042                 modest_ui_actions_on_msg_view_window_move_to (action,
5043                                 dst_folder,
5044                                 MODEST_MSG_VIEW_WINDOW (win));
5045         }
5046
5047         if (dst_folder)
5048                 g_object_unref (dst_folder);
5049 }
5050
5051 /*
5052  * Calls #HeadersFunc for each header already selected in the main
5053  * window or the message currently being shown in the msg view window
5054  */
5055 static void
5056 do_headers_action (ModestWindow *win, 
5057                    HeadersFunc func,
5058                    gpointer user_data)
5059 {
5060         TnyList *headers_list = NULL;
5061         TnyIterator *iter = NULL;
5062         TnyHeader *header = NULL;
5063         TnyFolder *folder = NULL;
5064
5065         /* Get headers */
5066         headers_list = get_selected_headers (win);
5067         if (!headers_list)
5068                 return;
5069
5070         /* Get the folder */
5071         iter = tny_list_create_iterator (headers_list);
5072         header = TNY_HEADER (tny_iterator_get_current (iter));
5073         if (header) {
5074                 folder = tny_header_get_folder (header);
5075                 g_object_unref (header);
5076         }
5077
5078         /* Call the function for each header */
5079         while (!tny_iterator_is_done (iter)) {
5080                 header = TNY_HEADER (tny_iterator_get_current (iter));
5081                 func (header, win, user_data);
5082                 g_object_unref (header);
5083                 tny_iterator_next (iter);
5084         }
5085
5086         /* Trick: do a poke status in order to speed up the signaling
5087            of observers */
5088         tny_folder_poke_status (folder);
5089
5090         /* Frees */
5091         g_object_unref (folder);
5092         g_object_unref (iter);
5093         g_object_unref (headers_list);
5094 }
5095
5096 void 
5097 modest_ui_actions_view_attachment (GtkAction *action,
5098                                    ModestWindow *window)
5099 {
5100         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5101                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5102         } else {
5103                 /* not supported window for this action */
5104                 g_return_if_reached ();
5105         }
5106 }
5107
5108 void
5109 modest_ui_actions_save_attachments (GtkAction *action,
5110                                     ModestWindow *window)
5111 {
5112         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5113                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5114         } else {
5115                 /* not supported window for this action */
5116                 g_return_if_reached ();
5117         }
5118 }
5119
5120 void
5121 modest_ui_actions_remove_attachments (GtkAction *action,
5122                                       ModestWindow *window)
5123 {
5124         if (MODEST_IS_MAIN_WINDOW (window)) {
5125                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5126         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5127                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5128         } else {
5129                 /* not supported window for this action */
5130                 g_return_if_reached ();
5131         }
5132 }
5133
5134 void 
5135 modest_ui_actions_on_settings (GtkAction *action, 
5136                                ModestWindow *win)
5137 {
5138         GtkWidget *dialog;
5139
5140         dialog = modest_platform_get_global_settings_dialog ();
5141         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5142         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5143         gtk_widget_show_all (dialog);
5144
5145         gtk_dialog_run (GTK_DIALOG (dialog));
5146
5147         gtk_widget_destroy (dialog);
5148 }
5149
5150 void 
5151 modest_ui_actions_on_help (GtkAction *action, 
5152                            GtkWindow *win)
5153 {
5154         const gchar *help_id;
5155
5156         g_return_if_fail (action);
5157         g_return_if_fail (win && GTK_IS_WINDOW(win));
5158         
5159         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5160         
5161         if (help_id)
5162                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5163         else
5164                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5165 }
5166
5167 static void
5168 retrieve_msg_contents_performer (gboolean canceled, 
5169                                  GError *err,
5170                                  GtkWindow *parent_window, 
5171                                  TnyAccount *account, 
5172                                  gpointer user_data)
5173 {
5174         ModestMailOperation *mail_op;
5175         TnyList *headers = TNY_LIST (user_data);
5176
5177         if (err || canceled) {
5178                 goto out;
5179         }
5180
5181         /* Create mail operation */
5182         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5183                                                                  modest_ui_actions_get_msgs_full_error_handler, 
5184                                                                  NULL, NULL);
5185         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5186         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5187
5188         /* Frees */
5189         g_object_unref (mail_op);
5190  out:
5191         g_object_unref (headers);
5192         g_object_unref (account);
5193 }
5194
5195 void 
5196 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5197                                             ModestWindow *window)
5198 {
5199         TnyList *headers = NULL;
5200         TnyAccount *account = NULL;
5201         TnyIterator *iter = NULL;
5202         TnyHeader *header = NULL;
5203         TnyFolder *folder = NULL;
5204
5205         /* Get headers */
5206         headers = get_selected_headers (window);
5207         if (!headers)
5208                 return;
5209
5210         /* Pick the account */
5211         iter = tny_list_create_iterator (headers);
5212         header = TNY_HEADER (tny_iterator_get_current (iter));
5213         folder = tny_header_get_folder (header);
5214         account = tny_folder_get_account (folder);
5215         g_object_unref (folder);
5216         g_object_unref (header);
5217         g_object_unref (iter);
5218
5219         /* Connect and perform the message retrieval */
5220         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5221                                              g_object_ref (account), 
5222                                              retrieve_msg_contents_performer, 
5223                                              g_object_ref (headers));
5224
5225         /* Frees */
5226         g_object_unref (account);
5227         g_object_unref (headers);
5228 }
5229
5230 void
5231 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5232 {
5233         g_return_if_fail (MODEST_IS_WINDOW (window));
5234
5235         /* Update dimmed */
5236         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5237 }
5238
5239 void
5240 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5241 {
5242         g_return_if_fail (MODEST_IS_WINDOW (window));
5243
5244         /* Update dimmed */
5245         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5246 }
5247
5248 void
5249 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5250                                           ModestWindow *window)
5251 {
5252         g_return_if_fail (MODEST_IS_WINDOW (window));
5253         
5254         /* Update dimmed */
5255         modest_ui_actions_check_menu_dimming_rules (window);
5256 }
5257
5258 void
5259 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5260                                           ModestWindow *window)
5261 {
5262         g_return_if_fail (MODEST_IS_WINDOW (window));
5263
5264         /* Update dimmed */
5265         modest_ui_actions_check_menu_dimming_rules (window);
5266 }
5267
5268 void
5269 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5270                                           ModestWindow *window)
5271 {
5272         g_return_if_fail (MODEST_IS_WINDOW (window));
5273
5274         /* Update dimmed */
5275         modest_ui_actions_check_menu_dimming_rules (window);
5276 }
5277
5278 void
5279 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5280                                             ModestWindow *window)
5281 {
5282         g_return_if_fail (MODEST_IS_WINDOW (window));
5283
5284         /* Update dimmed */
5285         modest_ui_actions_check_menu_dimming_rules (window);
5286 }
5287
5288 void
5289 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5290                                           ModestWindow *window)
5291 {
5292         g_return_if_fail (MODEST_IS_WINDOW (window));
5293
5294         /* Update dimmed */
5295         modest_ui_actions_check_menu_dimming_rules (window);
5296 }
5297
5298 void
5299 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5300                                           ModestWindow *window)
5301 {
5302         g_return_if_fail (MODEST_IS_WINDOW (window));
5303
5304         /* Update dimmed */
5305         modest_ui_actions_check_menu_dimming_rules (window);
5306 }
5307
5308 void
5309 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5310                                                  ModestWindow *window)
5311 {
5312         g_return_if_fail (MODEST_IS_WINDOW (window));
5313
5314         /* Update dimmed */
5315         modest_ui_actions_check_menu_dimming_rules (window);
5316 }
5317
5318 void
5319 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5320                                                      ModestWindow *window)
5321 {
5322         g_return_if_fail (MODEST_IS_WINDOW (window));
5323
5324         /* Update dimmed */
5325         modest_ui_actions_check_menu_dimming_rules (window);
5326 }
5327
5328 void
5329 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5330                                                      ModestWindow *window)
5331 {
5332         g_return_if_fail (MODEST_IS_WINDOW (window));
5333
5334         /* Update dimmed */
5335         modest_ui_actions_check_menu_dimming_rules (window);
5336 }
5337
5338 void
5339 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5340 {
5341         g_return_if_fail (MODEST_IS_WINDOW (window));
5342
5343         modest_platform_show_search_messages (GTK_WINDOW (window));
5344 }
5345
5346 void     
5347 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5348 {
5349         g_return_if_fail (MODEST_IS_WINDOW (win));
5350         modest_platform_show_addressbook (GTK_WINDOW (win));
5351 }
5352
5353
5354 void
5355 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5356                                           ModestWindow *window)
5357 {
5358         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5359
5360         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5361 }
5362
5363 static void 
5364 on_send_receive_finished (ModestMailOperation  *mail_op, 
5365                            gpointer user_data)
5366 {
5367         GtkWidget *header_view, *folder_view;
5368         TnyFolderStore *folder_store;
5369         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5370
5371         /* Set send/receive operation finished */       
5372         modest_main_window_notify_send_receive_completed (main_win);
5373
5374         /* Don't refresh the current folder if there were any errors */
5375         if (modest_mail_operation_get_status (mail_op) !=
5376             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5377                 return;
5378         
5379         /* Refresh the current folder if we're viewing a window. We do
5380            this because the user won't be able to see the new mails in
5381            the selected folder after a Send&Receive because it only
5382            performs a poke_status, i.e, only the number of read/unread
5383            messages is updated, but the new headers are not
5384            downloaded */
5385         folder_view = modest_main_window_get_child_widget (main_win, 
5386                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5387         if (!folder_view)
5388                 return;
5389
5390         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5391         
5392         /* Do not need to refresh INBOX again because the
5393            update_account does it always automatically */
5394         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5395             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5396                 ModestMailOperation *refresh_op;
5397
5398                 header_view = modest_main_window_get_child_widget (main_win,
5399                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5400                 
5401                 /* We do not need to set the contents style
5402                    because it hasn't changed. We also do not
5403                    need to save the widget status. Just force
5404                    a refresh */
5405                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5406                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5407                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5408                                                       folder_refreshed_cb, main_win);
5409                 g_object_unref (refresh_op);
5410         }
5411         
5412         if (folder_store)
5413                 g_object_unref (folder_store);
5414 }
5415
5416
5417 void 
5418 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5419                                                 TnyHeader *header, 
5420                                                 TnyMsg *msg, 
5421                                                 GError *err, 
5422                                                 gpointer user_data)
5423 {
5424         const gchar* server_name = NULL;
5425         TnyTransportAccount *server_account;
5426         gchar *message = NULL;
5427
5428         /* Don't show anything if the user cancelled something */
5429         if (err->code == TNY_SYSTEM_ERROR_CANCEL)
5430                 return;
5431
5432         /* Get the server name: */
5433         server_account = 
5434                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5435         if (server_account) {
5436                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5437                         
5438                 g_object_unref (server_account);
5439                 server_account = NULL;
5440         }
5441         
5442         g_return_if_fail (server_name);
5443
5444         /* Show the appropriate message text for the GError: */
5445         switch (err->code) {
5446         case TNY_SERVICE_ERROR_CONNECT:
5447                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5448                 break;
5449         case TNY_SERVICE_ERROR_AUTHENTICATE:
5450                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5451                 break;
5452         case TNY_SERVICE_ERROR_SEND:
5453                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5454                 break;
5455         case TNY_SERVICE_ERROR_UNAVAILABLE:
5456                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5457                 break;
5458         default:
5459                 g_warning ("%s: unexpected ERROR %d",
5460                            __FUNCTION__, err->code);
5461                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5462                 break;  
5463         }
5464         
5465         /* TODO if the username or the password where not defined we
5466            should show the Accounts Settings dialog or the Connection
5467            specific SMTP server window */
5468
5469         modest_platform_run_information_dialog (NULL, message);
5470         g_free (message);
5471 }
5472
5473 void
5474 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5475                                                 gchar *msg_id, 
5476                                                 guint status,
5477                                                 gpointer user_data)
5478 {
5479         ModestMainWindow *main_window = NULL;
5480         ModestWindowMgr *mgr = NULL;
5481         GtkWidget *folder_view = NULL, *header_view = NULL;
5482         TnyFolderStore *selected_folder = NULL;
5483         TnyFolderType folder_type;
5484
5485         mgr = modest_runtime_get_window_mgr ();
5486         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5487                                                                              FALSE));/* don't create */
5488         if (!main_window)
5489                 return;
5490
5491         /* Check if selected folder is OUTBOX */
5492         folder_view = modest_main_window_get_child_widget (main_window,
5493                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5494         header_view = modest_main_window_get_child_widget (main_window,
5495                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5496
5497         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5498         if (!TNY_IS_FOLDER (selected_folder)) 
5499                 goto frees;
5500
5501         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5502 #if GTK_CHECK_VERSION(2, 8, 0) 
5503         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5504         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5505                 GtkTreeViewColumn *tree_column;
5506
5507                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5508                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5509                 gtk_tree_view_column_queue_resize (tree_column);
5510         }
5511 #else
5512         gtk_widget_queue_draw (header_view);
5513 #endif          
5514
5515         /* Rerun dimming rules, because the message could become deletable for example */
5516         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5517                                                  MODEST_DIMMING_RULES_TOOLBAR);
5518         
5519         /* Free */
5520  frees:
5521         if (selected_folder != NULL)
5522                 g_object_unref (selected_folder);
5523 }
5524
5525 void 
5526 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5527                                                TnyAccount *account)
5528 {
5529         ModestTransportStoreProtocol proto;
5530         const gchar *proto_name;
5531         gchar *error_note = NULL;
5532         
5533         proto_name = tny_account_get_proto (account);
5534         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5535         
5536         switch (proto) {
5537         case MODEST_PROTOCOL_STORE_POP:
5538                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5539                                               tny_account_get_hostname (account));
5540                 break;
5541         case MODEST_PROTOCOL_STORE_IMAP:
5542                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5543                                               tny_account_get_hostname (account));
5544                 break;
5545         case MODEST_PROTOCOL_STORE_MAILDIR:
5546         case MODEST_PROTOCOL_STORE_MBOX:
5547                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5548                 break;
5549         default:
5550                 g_warning ("%s: This should not be reached", __FUNCTION__);
5551         }
5552
5553         if (error_note) {
5554                 modest_platform_run_information_dialog (parent_window, error_note);
5555                 g_free (error_note);
5556         }
5557 }
5558
5559 gchar *
5560 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5561 {
5562         gchar *msg = NULL;
5563         TnyFolderStore *folder = NULL;
5564         TnyAccount *account = NULL;
5565         ModestTransportStoreProtocol proto;
5566         TnyHeader *header = NULL;
5567
5568         if (MODEST_IS_MAIN_WINDOW (win)) {
5569                 GtkWidget *header_view;
5570                 TnyList* headers = NULL;
5571                 TnyIterator *iter;
5572                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5573                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5574                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5575                 if (!headers || tny_list_get_length (headers) == 0) {
5576                         if (headers)
5577                                 g_object_unref (headers);
5578                         return NULL;
5579                 }
5580                 iter = tny_list_create_iterator (headers);
5581                 header = TNY_HEADER (tny_iterator_get_current (iter));
5582                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5583                 g_object_unref (iter);
5584                 g_object_unref (headers);
5585         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5586                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5587                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5588         }
5589
5590         /* Get the account type */
5591         account = tny_folder_get_account (TNY_FOLDER (folder));
5592         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5593         if (proto == MODEST_PROTOCOL_STORE_POP) {
5594                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5595         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5596                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
5597                                        tny_header_get_subject (header));
5598         } else {
5599                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5600         }
5601
5602         /* Frees */
5603         g_object_unref (account);
5604         g_object_unref (folder);
5605         g_object_unref (header);
5606
5607         return msg;
5608 }