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