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