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