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