* Fixes NB#87102, append the signature at the end of the message
[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 (data->folder);
3302                 g_object_unref (mail_op);
3303         }
3304
3305         g_free (data->new_name);
3306         g_free (data);
3307 }
3308
3309 void 
3310 modest_ui_actions_on_rename_folder (GtkAction *action,
3311                                      ModestMainWindow *main_window)
3312 {
3313         TnyFolderStore *folder;
3314         GtkWidget *folder_view;
3315         GtkWidget *header_view; 
3316
3317         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3318
3319         folder_view = modest_main_window_get_child_widget (main_window,
3320                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3321         if (!folder_view)
3322                 return;
3323
3324         header_view = modest_main_window_get_child_widget (main_window,
3325                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3326         
3327         if (!header_view)
3328                 return;
3329
3330         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3331
3332         if (!folder)
3333                 return;
3334
3335         if (TNY_IS_FOLDER (folder)) {
3336                 gchar *folder_name;
3337                 gint response;
3338                 const gchar *current_name;
3339                 TnyFolderStore *parent;
3340                 gboolean do_rename = TRUE;
3341
3342                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3343                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3344                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
3345                                                                      parent, current_name, 
3346                                                                      &folder_name);
3347                 g_object_unref (parent);
3348
3349                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3350                         do_rename = FALSE;
3351                 } else {
3352                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3353                         rename_folder_data->folder = g_object_ref (folder);
3354                         rename_folder_data->new_name = folder_name;
3355                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3356                                         folder, on_rename_folder_performer, rename_folder_data);
3357                 }
3358         }
3359         g_object_unref (folder);
3360 }
3361
3362 static void
3363 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3364                                                gpointer user_data)
3365 {
3366         GObject *win = modest_mail_operation_get_source (mail_op);
3367
3368         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3369                                                 _("mail_in_ui_folder_delete_error"),
3370                                                 FALSE);
3371         g_object_unref (win);
3372 }
3373
3374 typedef struct {
3375         TnyFolderStore *folder;
3376         gboolean move_to_trash;
3377 } DeleteFolderInfo;
3378
3379 static void
3380 on_delete_folder_cb (gboolean canceled, 
3381                   GError *err,
3382                   GtkWindow *parent_window, 
3383                   TnyAccount *account, 
3384                   gpointer user_data)
3385 {
3386         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3387         GtkWidget *folder_view;
3388         ModestMailOperation *mail_op;
3389         GtkTreeSelection *sel;
3390         
3391         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3392                 g_object_unref (G_OBJECT (info->folder));
3393                 g_free (info);
3394                 return;
3395         }
3396         
3397         folder_view = modest_main_window_get_child_widget (
3398                         MODEST_MAIN_WINDOW (parent_window),
3399                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3400
3401         /* Unselect the folder before deleting it to free the headers */
3402         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3403         gtk_tree_selection_unselect_all (sel);
3404
3405         /* Create the mail operation */
3406         mail_op =
3407                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3408                                 modest_ui_actions_delete_folder_error_handler,
3409                                 NULL, NULL);
3410
3411         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3412                         mail_op);
3413         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3414         
3415         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3416
3417         g_object_unref (G_OBJECT (mail_op));
3418         g_object_unref (G_OBJECT (info->folder));
3419         g_free (info);
3420 }
3421
3422 static void
3423 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3424 {
3425         TnyFolderStore *folder;
3426         GtkWidget *folder_view;
3427         gint response;
3428         gchar *message;
3429         
3430         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3431
3432         folder_view = modest_main_window_get_child_widget (main_window,
3433                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3434         if (!folder_view)
3435                 return;
3436
3437         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3438
3439         /* Show an error if it's an account */
3440         if (!TNY_IS_FOLDER (folder)) {
3441                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3442                                                         _("mail_in_ui_folder_delete_error"),
3443                                                         FALSE);
3444                 g_object_unref (G_OBJECT (folder));
3445                 return;
3446         }
3447
3448         /* Ask the user */      
3449         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3450                                     tny_folder_get_name (TNY_FOLDER (folder)));
3451         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3452                                                             (const gchar *) message);
3453         g_free (message);
3454
3455         if (response == GTK_RESPONSE_OK) {
3456                 DeleteFolderInfo *info;
3457                 info = g_new0(DeleteFolderInfo, 1);
3458                 info->folder = folder;
3459                 info->move_to_trash = move_to_trash;
3460                 g_object_ref (G_OBJECT (info->folder));
3461                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3462                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3463                                                                TRUE,
3464                                                                TNY_FOLDER_STORE (account), 
3465                                                                on_delete_folder_cb, info);
3466                 g_object_unref (account);
3467         }
3468         g_object_unref (G_OBJECT (folder));
3469 }
3470
3471 void 
3472 modest_ui_actions_on_delete_folder (GtkAction *action,
3473                                      ModestMainWindow *main_window)
3474 {
3475         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3476         
3477         delete_folder (main_window, FALSE);
3478 }
3479
3480 void 
3481 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3482 {
3483         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3484         
3485         delete_folder (main_window, TRUE);
3486 }
3487
3488
3489 typedef struct _PasswordDialogFields {
3490         GtkWidget *username;
3491         GtkWidget *password;
3492         GtkWidget *dialog;
3493 } PasswordDialogFields;
3494
3495 static void
3496 password_dialog_check_field (GtkEditable *editable,
3497                              PasswordDialogFields *fields)
3498 {
3499         const gchar *value;
3500         gboolean any_value_empty = FALSE;
3501
3502         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3503         if ((value == NULL) || value[0] == '\0') {
3504                 any_value_empty = TRUE;
3505         }
3506         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3507         if ((value == NULL) || value[0] == '\0') {
3508                 any_value_empty = TRUE;
3509         }
3510         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3511 }
3512
3513 void
3514 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3515                                          const gchar* server_account_name,
3516                                          gchar **username,
3517                                          gchar **password, 
3518                                          gboolean *cancel, 
3519                                          gboolean *remember,
3520                                          ModestMainWindow *main_window)
3521 {
3522         g_return_if_fail(server_account_name);
3523         gboolean completed = FALSE;
3524         PasswordDialogFields *fields = NULL;
3525         
3526         /* Initalize output parameters: */
3527         if (cancel)
3528                 *cancel = FALSE;
3529                 
3530         if (remember)
3531                 *remember = TRUE;
3532                 
3533 #ifdef MODEST_PLATFORM_MAEMO
3534         /* Maemo uses a different (awkward) button order,
3535          * It should probably just use gtk_alternative_dialog_button_order ().
3536          */
3537         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3538                                               NULL,
3539                                               GTK_DIALOG_MODAL,
3540                                               _("mcen_bd_dialog_ok"),
3541                                               GTK_RESPONSE_ACCEPT,
3542                                               _("mcen_bd_dialog_cancel"),
3543                                               GTK_RESPONSE_REJECT,
3544                                               NULL);
3545 #else
3546         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3547                                               NULL,
3548                                               GTK_DIALOG_MODAL,
3549                                               GTK_STOCK_CANCEL,
3550                                               GTK_RESPONSE_REJECT,
3551                                               GTK_STOCK_OK,
3552                                               GTK_RESPONSE_ACCEPT,
3553                                               NULL);
3554 #endif /* MODEST_PLATFORM_MAEMO */
3555
3556         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3557         
3558         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3559                 modest_runtime_get_account_mgr(), server_account_name);
3560         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3561                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3562                 if (cancel)
3563                         *cancel = TRUE;
3564                 return;
3565         }
3566         
3567         /* This causes a warning because the logical ID has no %s in it, 
3568          * though the translation does, but there is not much we can do about that: */
3569         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3570         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3571                             FALSE, FALSE, 0);
3572         g_free (txt);
3573         g_free (server_name);
3574         server_name = NULL;
3575
3576         /* username: */
3577         gchar *initial_username = modest_account_mgr_get_server_account_username (
3578                 modest_runtime_get_account_mgr(), server_account_name);
3579         
3580         GtkWidget *entry_username = gtk_entry_new ();
3581         if (initial_username)
3582                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3583         /* Dim this if a connection has ever succeeded with this username,
3584          * as per the UI spec: */
3585         /* const gboolean username_known =  */
3586         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3587         /*              modest_runtime_get_account_mgr(), server_account_name); */
3588         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3589
3590         /* We drop the username sensitive code and disallow changing it here
3591          * as tinymail does not support really changing the username in the callback
3592          */
3593         gtk_widget_set_sensitive (entry_username, FALSE);
3594
3595 #ifdef MODEST_PLATFORM_MAEMO
3596         /* Auto-capitalization is the default, so let's turn it off: */
3597         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3598         
3599         /* Create a size group to be used by all captions.
3600          * Note that HildonCaption does not create a default size group if we do not specify one.
3601          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3602         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3603         
3604         GtkWidget *caption = hildon_caption_new (sizegroup, 
3605                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3606         gtk_widget_show (entry_username);
3607         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3608                 FALSE, FALSE, MODEST_MARGIN_HALF);
3609         gtk_widget_show (caption);
3610 #else 
3611         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3612                             TRUE, FALSE, 0);
3613 #endif /* MODEST_PLATFORM_MAEMO */      
3614                             
3615         /* password: */
3616         GtkWidget *entry_password = gtk_entry_new ();
3617         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3618         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3619         
3620 #ifdef MODEST_PLATFORM_MAEMO
3621         /* Auto-capitalization is the default, so let's turn it off: */
3622         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3623                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3624         
3625         caption = hildon_caption_new (sizegroup, 
3626                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3627         gtk_widget_show (entry_password);
3628         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3629                 FALSE, FALSE, MODEST_MARGIN_HALF);
3630         gtk_widget_show (caption);
3631         g_object_unref (sizegroup);
3632 #else 
3633         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3634                             TRUE, FALSE, 0);
3635 #endif /* MODEST_PLATFORM_MAEMO */      
3636
3637         if (initial_username != NULL)
3638                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3639                                 
3640 /* This is not in the Maemo UI spec:
3641         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3642         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3643                             TRUE, FALSE, 0);
3644 */
3645
3646         fields = g_slice_new0 (PasswordDialogFields);
3647         fields->username = entry_username;
3648         fields->password = entry_password;
3649         fields->dialog = dialog;
3650
3651         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3652         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3653         password_dialog_check_field (NULL, fields);
3654
3655         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3656
3657         while (!completed) {
3658         
3659                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3660                         if (username) {
3661                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3662                                 
3663                                 /* Note that an empty field becomes the "" string */
3664                                 if (*username && strlen (*username) > 0) {
3665                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3666                                                                                         server_account_name, 
3667                                                                                         *username);
3668                                         completed = TRUE;
3669                                 
3670                                         const gboolean username_was_changed = 
3671                                                 (strcmp (*username, initial_username) != 0);
3672                                         if (username_was_changed) {
3673                                                 g_warning ("%s: tinymail does not yet support changing the "
3674                                                            "username in the get_password() callback.\n", __FUNCTION__);
3675                                         }
3676                                 } else {
3677                                         /* Show error */
3678                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3679                                                                             _("mcen_ib_username_pw_incorrect"));
3680                                         completed = FALSE;
3681                                 }
3682                         }
3683                         
3684                         if (password) {
3685                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3686                         
3687                                 /* We do not save the password in the configuration, 
3688                                  * because this function is only called for passwords that should 
3689                                  * not be remembered:
3690                                  modest_server_account_set_password (
3691                                  modest_runtime_get_account_mgr(), server_account_name, 
3692                                  *password);
3693                                  */
3694                         }                       
3695                         if (cancel)
3696                                 *cancel   = FALSE;                      
3697                 } else {
3698                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3699                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3700                         completed = TRUE;
3701                         if (username)
3702                                 *username = NULL;                       
3703                         if (password)
3704                                 *password = NULL;                       
3705                         if (cancel)
3706                                 *cancel   = TRUE;
3707                 }
3708         }
3709
3710 /* This is not in the Maemo UI spec:
3711         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3712                 *remember = TRUE;
3713         else
3714                 *remember = FALSE;
3715 */
3716
3717         gtk_widget_destroy (dialog);
3718         g_slice_free (PasswordDialogFields, fields);
3719         
3720         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3721 }
3722
3723 void
3724 modest_ui_actions_on_cut (GtkAction *action,
3725                           ModestWindow *window)
3726 {
3727         GtkWidget *focused_widget;
3728         GtkClipboard *clipboard;
3729
3730         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3731         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3732         if (GTK_IS_EDITABLE (focused_widget)) {
3733                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3734                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3735                 gtk_clipboard_store (clipboard);
3736         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3737                 GtkTextBuffer *buffer;
3738
3739                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3740                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3741                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3742                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3743                         gtk_clipboard_store (clipboard);
3744                 }
3745         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3746                 TnyList *header_list = modest_header_view_get_selected_headers (
3747                                 MODEST_HEADER_VIEW (focused_widget));
3748                 gboolean continue_download = FALSE;
3749                 gint num_of_unc_msgs;
3750
3751                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3752
3753                 if (num_of_unc_msgs) {
3754                         TnyAccount *account = get_account_from_header_list (header_list);
3755                         if (account) {
3756                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3757                                 g_object_unref (account);
3758                         }
3759                 }
3760
3761                 if (num_of_unc_msgs == 0 || continue_download) {
3762 /*                      modest_platform_information_banner (
3763                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3764                         modest_header_view_cut_selection (
3765                                         MODEST_HEADER_VIEW (focused_widget));
3766                 }
3767
3768                 g_object_unref (header_list);
3769         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3770                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3771         }
3772 }
3773
3774 void
3775 modest_ui_actions_on_copy (GtkAction *action,
3776                            ModestWindow *window)
3777 {
3778         GtkClipboard *clipboard;
3779         GtkWidget *focused_widget;
3780         gboolean copied = TRUE;
3781
3782         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3783         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3784
3785         if (GTK_IS_LABEL (focused_widget)) {
3786                 gchar *selection;
3787                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3788                 gtk_clipboard_set_text (clipboard, selection, -1);
3789                 g_free (selection);
3790                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3791                 gtk_clipboard_store (clipboard);
3792         } else if (GTK_IS_EDITABLE (focused_widget)) {
3793                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3794                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3795                 gtk_clipboard_store (clipboard);
3796         } else if (GTK_IS_HTML (focused_widget)) {
3797                 const gchar *sel;
3798                 int len = -1;
3799                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3800                 if ((sel == NULL) || (sel[0] == '\0')) {
3801                         copied = FALSE;
3802                 } else {
3803                         gtk_html_copy (GTK_HTML (focused_widget));
3804                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3805                         gtk_clipboard_store (clipboard);
3806                 }
3807         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3808                 GtkTextBuffer *buffer;
3809                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3810                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3811                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3812                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3813                         gtk_clipboard_store (clipboard);
3814                 }
3815         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3816                 TnyList *header_list = modest_header_view_get_selected_headers (
3817                                 MODEST_HEADER_VIEW (focused_widget));
3818                 gboolean continue_download = FALSE;
3819                 gint num_of_unc_msgs;
3820
3821                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3822
3823                 if (num_of_unc_msgs) {
3824                         TnyAccount *account = get_account_from_header_list (header_list);
3825                         if (account) {
3826                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3827                                 g_object_unref (account);
3828                         }
3829                 }
3830
3831                 if (num_of_unc_msgs == 0 || continue_download) {
3832                         modest_platform_information_banner (
3833                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3834                         modest_header_view_copy_selection (
3835                                         MODEST_HEADER_VIEW (focused_widget));
3836                 } else
3837                         copied = FALSE;
3838
3839                 g_object_unref (header_list);
3840
3841         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3842                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3843         }
3844
3845         /* Show information banner if there was a copy to clipboard */
3846         if(copied)
3847                 modest_platform_information_banner (
3848                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3849 }
3850
3851 void
3852 modest_ui_actions_on_undo (GtkAction *action,
3853                            ModestWindow *window)
3854 {
3855         ModestEmailClipboard *clipboard = NULL;
3856
3857         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3858                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3859         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3860                 /* Clear clipboard source */
3861                 clipboard = modest_runtime_get_email_clipboard ();
3862                 modest_email_clipboard_clear (clipboard);               
3863         }
3864         else {
3865                 g_return_if_reached ();
3866         }
3867 }
3868
3869 void
3870 modest_ui_actions_on_redo (GtkAction *action,
3871                            ModestWindow *window)
3872 {
3873         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3874                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3875         }
3876         else {
3877                 g_return_if_reached ();
3878         }
3879 }
3880
3881
3882 static void
3883 destroy_information_note (ModestMailOperation *mail_op, 
3884                           gpointer user_data)
3885 {
3886         /* destroy information note */
3887         gtk_widget_destroy (GTK_WIDGET(user_data));
3888 }
3889
3890 static void
3891 destroy_folder_information_note (ModestMailOperation *mail_op, 
3892                                  TnyFolder *new_folder,
3893                                  gpointer user_data)
3894 {
3895         /* destroy information note */
3896         gtk_widget_destroy (GTK_WIDGET(user_data));
3897 }
3898
3899
3900 static void
3901 paste_as_attachment_free (gpointer data)
3902 {
3903         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3904
3905         if (helper->banner) {
3906                 gtk_widget_destroy (helper->banner);
3907                 g_object_unref (helper->banner);
3908         }
3909         g_free (helper);
3910 }
3911
3912 static void
3913 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3914                             TnyHeader *header,
3915                             TnyMsg *msg,
3916                             gpointer userdata)
3917 {
3918         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3919         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3920
3921         if (msg == NULL)
3922                 return;
3923
3924         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3925         
3926 }
3927
3928 void
3929 modest_ui_actions_on_paste (GtkAction *action,
3930                             ModestWindow *window)
3931 {
3932         GtkWidget *focused_widget = NULL;
3933         GtkWidget *inf_note = NULL;
3934         ModestMailOperation *mail_op = NULL;
3935
3936         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3937         if (GTK_IS_EDITABLE (focused_widget)) {
3938                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3939         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3940                 ModestEmailClipboard *e_clipboard = NULL;
3941                 e_clipboard = modest_runtime_get_email_clipboard ();
3942                 if (modest_email_clipboard_cleared (e_clipboard)) {
3943                         GtkTextBuffer *buffer;
3944                         GtkClipboard *clipboard;
3945
3946                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3947                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3948                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3949                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3950                         ModestMailOperation *mail_op;
3951                         TnyFolder *src_folder;
3952                         TnyList *data;
3953                         gboolean delete;
3954                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3955                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3956                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3957                                                                            _CS("ckct_nw_pasting"));
3958                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3959                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3960                         if (helper->banner != NULL) {
3961                                 g_object_ref (G_OBJECT (helper->banner));
3962                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3963                         }
3964
3965                         if (data != NULL) {
3966                                 modest_mail_operation_get_msgs_full (mail_op, 
3967                                                                      data,
3968                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3969                                                                      helper,
3970                                                                      paste_as_attachment_free);
3971                         }
3972                 }
3973         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3974                 ModestEmailClipboard *clipboard = NULL;
3975                 TnyFolder *src_folder = NULL;
3976                 TnyFolderStore *folder_store = NULL;
3977                 TnyList *data = NULL;           
3978                 gboolean delete = FALSE;
3979                 
3980                 /* Check clipboard source */
3981                 clipboard = modest_runtime_get_email_clipboard ();
3982                 if (modest_email_clipboard_cleared (clipboard)) 
3983                         return;
3984                 
3985                 /* Get elements to paste */
3986                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3987
3988                 /* Create a new mail operation */
3989                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3990                 
3991                 /* Get destination folder */
3992                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3993
3994                 /* transfer messages  */
3995                 if (data != NULL) {
3996                         gint response = 0;
3997
3998                         /* Ask for user confirmation */
3999                         response = 
4000                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4001                                                                              TNY_FOLDER (folder_store), 
4002                                                                              delete,
4003                                                                              data);
4004                         
4005                         if (response == GTK_RESPONSE_OK) {
4006                                 /* Launch notification */
4007                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4008                                                                              _CS("ckct_nw_pasting"));
4009                                 if (inf_note != NULL)  {
4010                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4011                                         gtk_widget_show (GTK_WIDGET(inf_note));
4012                                 }
4013
4014                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4015                                 modest_mail_operation_xfer_msgs (mail_op, 
4016                                                                  data,
4017                                                                  TNY_FOLDER (folder_store),
4018                                                                  delete,
4019                                                                  destroy_information_note,
4020                                                                  inf_note);                             
4021                         } else {
4022                                 g_object_unref (mail_op);
4023                         }
4024                         
4025                 } else if (src_folder != NULL) {                        
4026                         /* Launch notification */
4027                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4028                                                                      _CS("ckct_nw_pasting"));
4029                         if (inf_note != NULL)  {
4030                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4031                                 gtk_widget_show (GTK_WIDGET(inf_note));
4032                         }
4033                         
4034                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4035                         modest_mail_operation_xfer_folder (mail_op, 
4036                                                            src_folder,
4037                                                            folder_store,
4038                                                            delete,
4039                                                            destroy_folder_information_note,
4040                                                            inf_note);
4041                 }
4042
4043                 /* Free */
4044                 if (data != NULL) 
4045                         g_object_unref (data);
4046                 if (src_folder != NULL) 
4047                         g_object_unref (src_folder);
4048                 if (folder_store != NULL) 
4049                         g_object_unref (folder_store);
4050         }
4051 }
4052
4053
4054 void
4055 modest_ui_actions_on_select_all (GtkAction *action,
4056                                  ModestWindow *window)
4057 {
4058         GtkWidget *focused_widget;
4059
4060         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4061         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4062                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4063         } else if (GTK_IS_LABEL (focused_widget)) {
4064                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4065         } else if (GTK_IS_EDITABLE (focused_widget)) {
4066                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4067         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4068                 GtkTextBuffer *buffer;
4069                 GtkTextIter start, end;
4070
4071                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4072                 gtk_text_buffer_get_start_iter (buffer, &start);
4073                 gtk_text_buffer_get_end_iter (buffer, &end);
4074                 gtk_text_buffer_select_range (buffer, &start, &end);
4075         } else if (GTK_IS_HTML (focused_widget)) {
4076                 gtk_html_select_all (GTK_HTML (focused_widget));
4077         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4078                 GtkWidget *header_view = focused_widget;
4079                 GtkTreeSelection *selection = NULL;
4080                 
4081                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4082                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4083                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4084                 }
4085                                 
4086                 /* Disable window dimming management */
4087                 modest_window_disable_dimming (MODEST_WINDOW(window));
4088                 
4089                 /* Select all messages */
4090                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4091                 gtk_tree_selection_select_all (selection);
4092
4093                 /* Set focuse on header view */
4094                 gtk_widget_grab_focus (header_view);
4095
4096                 /* Enable window dimming management */
4097                 modest_window_enable_dimming (MODEST_WINDOW(window));
4098                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4099                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4100         }
4101
4102 }
4103
4104 void
4105 modest_ui_actions_on_mark_as_read (GtkAction *action,
4106                                    ModestWindow *window)
4107 {       
4108         g_return_if_fail (MODEST_IS_WINDOW(window));
4109                 
4110         /* Mark each header as read */
4111         do_headers_action (window, headers_action_mark_as_read, NULL);
4112 }
4113
4114 void
4115 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4116                                      ModestWindow *window)
4117 {       
4118         g_return_if_fail (MODEST_IS_WINDOW(window));
4119                 
4120         /* Mark each header as read */
4121         do_headers_action (window, headers_action_mark_as_unread, NULL);
4122 }
4123
4124 void
4125 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4126                                   GtkRadioAction *selected,
4127                                   ModestWindow *window)
4128 {
4129         gint value;
4130
4131         value = gtk_radio_action_get_current_value (selected);
4132         if (MODEST_IS_WINDOW (window)) {
4133                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4134         }
4135 }
4136
4137 void
4138 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4139                                                GtkRadioAction *selected,
4140                                                ModestWindow *window)
4141 {
4142         TnyHeaderFlags flags;
4143         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4144
4145         flags = gtk_radio_action_get_current_value (selected);
4146         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4147 }
4148
4149 void
4150 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4151                                                   GtkRadioAction *selected,
4152                                                   ModestWindow *window)
4153 {
4154         gint file_format;
4155
4156         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4157
4158         file_format = gtk_radio_action_get_current_value (selected);
4159         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4160 }
4161
4162
4163 void
4164 modest_ui_actions_on_zoom_plus (GtkAction *action,
4165                                 ModestWindow *window)
4166 {
4167         g_return_if_fail (MODEST_IS_WINDOW (window));
4168
4169         modest_window_zoom_plus (MODEST_WINDOW (window));
4170 }
4171
4172 void     
4173 modest_ui_actions_on_zoom_minus (GtkAction *action,
4174                                  ModestWindow *window)
4175 {
4176         g_return_if_fail (MODEST_IS_WINDOW (window));
4177
4178         modest_window_zoom_minus (MODEST_WINDOW (window));
4179 }
4180
4181 void     
4182 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4183                                            ModestWindow *window)
4184 {
4185         ModestWindowMgr *mgr;
4186         gboolean fullscreen, active;
4187         g_return_if_fail (MODEST_IS_WINDOW (window));
4188
4189         mgr = modest_runtime_get_window_mgr ();
4190
4191         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4192         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4193
4194         if (active != fullscreen) {
4195                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4196                 gtk_window_present (GTK_WINDOW (window));
4197         }
4198 }
4199
4200 void
4201 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4202                                         ModestWindow *window)
4203 {
4204         ModestWindowMgr *mgr;
4205         gboolean fullscreen;
4206
4207         g_return_if_fail (MODEST_IS_WINDOW (window));
4208
4209         mgr = modest_runtime_get_window_mgr ();
4210         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4211         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4212
4213         gtk_window_present (GTK_WINDOW (window));
4214 }
4215
4216 /* 
4217  * Used by modest_ui_actions_on_details to call do_headers_action 
4218  */
4219 static void
4220 headers_action_show_details (TnyHeader *header, 
4221                              ModestWindow *window,
4222                              gpointer user_data)
4223
4224 {
4225         GtkWidget *dialog;
4226         
4227         /* Create dialog */
4228         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4229
4230         /* Run dialog */
4231         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4232         gtk_widget_show_all (dialog);
4233         gtk_dialog_run (GTK_DIALOG (dialog));
4234
4235         gtk_widget_destroy (dialog);
4236 }
4237
4238 /*
4239  * Show the folder details in a ModestDetailsDialog widget
4240  */
4241 static void
4242 show_folder_details (TnyFolder *folder, 
4243                      GtkWindow *window)
4244 {
4245         GtkWidget *dialog;
4246         
4247         /* Create dialog */
4248         dialog = modest_details_dialog_new_with_folder (window, folder);
4249
4250         /* Run dialog */
4251         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4252         gtk_widget_show_all (dialog);
4253         gtk_dialog_run (GTK_DIALOG (dialog));
4254
4255         gtk_widget_destroy (dialog);
4256 }
4257
4258 /*
4259  * Show the header details in a ModestDetailsDialog widget
4260  */
4261 void     
4262 modest_ui_actions_on_details (GtkAction *action, 
4263                               ModestWindow *win)
4264 {
4265         TnyList * headers_list;
4266         TnyIterator *iter;
4267         TnyHeader *header;              
4268
4269         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4270                 TnyMsg *msg;
4271
4272                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4273                 if (!msg)
4274                         return;
4275                 g_object_unref (msg);           
4276
4277                 headers_list = get_selected_headers (win);
4278                 if (!headers_list)
4279                         return;
4280
4281                 iter = tny_list_create_iterator (headers_list);
4282
4283                 header = TNY_HEADER (tny_iterator_get_current (iter));
4284                 if (header) {
4285                         headers_action_show_details (header, win, NULL);
4286                         g_object_unref (header);
4287                 }
4288
4289                 g_object_unref (iter);
4290                 g_object_unref (headers_list);
4291
4292         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4293                 GtkWidget *folder_view, *header_view;
4294
4295                 /* Check which widget has the focus */
4296                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4297                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4298                 if (gtk_widget_is_focus (folder_view)) {
4299                         TnyFolderStore *folder_store
4300                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4301                         if (!folder_store) {
4302                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4303                                 return; 
4304                         }
4305                         /* Show only when it's a folder */
4306                         /* This function should not be called for account items, 
4307                          * because we dim the menu item for them. */
4308                         if (TNY_IS_FOLDER (folder_store)) {
4309                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4310                         }
4311
4312                         g_object_unref (folder_store);
4313
4314                 } else {
4315                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4316                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4317                         /* Show details of each header */
4318                         do_headers_action (win, headers_action_show_details, header_view);
4319                 }
4320         }
4321 }
4322
4323 void     
4324 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4325                                      ModestMsgEditWindow *window)
4326 {
4327         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4328
4329         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4330 }
4331
4332 void     
4333 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4334                                       ModestMsgEditWindow *window)
4335 {
4336         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4337
4338         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4339 }
4340
4341 void
4342 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4343                                        ModestMainWindow *main_window)
4344 {
4345         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4346
4347         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4348                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4349         else
4350                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4351 }
4352
4353 void 
4354 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4355                                      ModestWindow *window)
4356 {
4357         gboolean active, fullscreen = FALSE;
4358         ModestWindowMgr *mgr;
4359
4360         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4361
4362         /* Check if we want to toggle the toolbar vuew in fullscreen
4363            or normal mode */
4364         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4365                      "ViewShowToolbarFullScreen")) {
4366                 fullscreen = TRUE;
4367         }
4368
4369         /* Toggle toolbar */
4370         mgr = modest_runtime_get_window_mgr ();
4371         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4372 }
4373
4374 void     
4375 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4376                                            ModestMsgEditWindow *window)
4377 {
4378         modest_msg_edit_window_select_font (window);
4379 }
4380
4381
4382 void
4383 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4384                                                   const gchar *display_name,
4385                                                   GtkWindow *window)
4386 {
4387         /* don't update the display name if it was already set;
4388          * updating the display name apparently is expensive */
4389         const gchar* old_name = gtk_window_get_title (window);
4390
4391         if (display_name == NULL)
4392                 display_name = " ";
4393
4394         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4395                 return; /* don't do anything */
4396
4397         /* This is usually used to change the title of the main window, which
4398          * is the one that holds the folder view. Note that this change can
4399          * happen even when the widget doesn't have the focus. */
4400         gtk_window_set_title (window, display_name);
4401
4402 }
4403
4404 void
4405 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4406 {
4407         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4408         modest_msg_edit_window_select_contacts (window);
4409 }
4410
4411 void
4412 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4413 {
4414         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4415         modest_msg_edit_window_check_names (window, FALSE);
4416 }
4417
4418 static void
4419 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4420 {
4421         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4422                                          GTK_WIDGET (user_data));
4423 }
4424
4425 /*
4426  * This function is used to track changes in the selection of the
4427  * folder view that is inside the "move to" dialog to enable/disable
4428  * the OK button because we do not want the user to select a disallowed
4429  * destination for a folder.
4430  * The user also not desired to be able to use NEW button on items where
4431  * folder creation is not possibel.
4432  */
4433 static void
4434 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4435                                             TnyFolderStore *folder_store,
4436                                             gboolean selected,
4437                                             gpointer user_data)
4438 {
4439         GtkWidget *dialog = NULL;
4440         GtkWidget *ok_button = NULL, *new_button = NULL;
4441         GList *children = NULL;
4442         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4443         gboolean moving_folder = FALSE;
4444         gboolean is_local_account = TRUE;
4445         GtkWidget *folder_view = NULL;
4446         ModestTnyFolderRules rules;
4447
4448         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4449         
4450         if (!selected)
4451                 return;
4452         
4453         /* Get the OK button */
4454         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4455         if (!dialog)
4456                 return;
4457
4458         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4459 #ifdef MODEST_PLATFORM_MAEMO
4460         ok_button = GTK_WIDGET (children->next->next->data);
4461         new_button = GTK_WIDGET (children->next->data);
4462 #else
4463         ok_button = GTK_WIDGET (children->data);
4464         new_button = GTK_WIDGET (children->next->next->data);
4465 #endif
4466         g_list_free (children);
4467
4468         /* check if folder_store is an remote account */
4469         if (TNY_IS_ACCOUNT (folder_store)) {
4470                 TnyAccount *local_account = NULL;
4471                 TnyAccount *mmc_account = NULL;
4472                 ModestTnyAccountStore *account_store = NULL;
4473
4474                 account_store = modest_runtime_get_account_store ();
4475                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4476                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4477
4478                 if ((gpointer) local_account != (gpointer) folder_store &&
4479                     (gpointer) mmc_account != (gpointer) folder_store) {
4480                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4481                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4482                         if (proto_name != NULL) {
4483                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4484                         }
4485                         is_local_account = FALSE;
4486                         /* New button should be dimmed on remote
4487                            POP account root */
4488                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4489                 }
4490                 g_object_unref (local_account);
4491                 g_object_unref (mmc_account);
4492         }
4493
4494         /* Check the target folder rules */
4495         if (TNY_IS_FOLDER (folder_store)) {
4496                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4497                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4498                         ok_sensitive = FALSE;
4499                         new_sensitive = FALSE;
4500                         goto end;
4501                 }
4502         }
4503
4504         /* Check if we're moving a folder */
4505         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4506                 /* Get the widgets */
4507                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4508                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4509                 if (gtk_widget_is_focus (folder_view))
4510                         moving_folder = TRUE;
4511         }
4512
4513         if (moving_folder) {
4514                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4515
4516                 /* Get the folder to move */
4517                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4518                 
4519                 /* Check that we're not moving to the same folder */
4520                 if (TNY_IS_FOLDER (moved_folder)) {
4521                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4522                         if (parent == folder_store)
4523                                 ok_sensitive = FALSE;
4524                         g_object_unref (parent);
4525                 } 
4526
4527                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4528                         /* Do not allow to move to an account unless it's the
4529                            local folders account */
4530                         if (!is_local_account)
4531                                 ok_sensitive = FALSE;
4532                 } 
4533
4534                 if (ok_sensitive && (moved_folder == folder_store)) {
4535                         /* Do not allow to move to itself */
4536                         ok_sensitive = FALSE;
4537                 }
4538                 g_object_unref (moved_folder);
4539         } else {
4540                 TnyFolder *src_folder = NULL;
4541
4542                 /* Moving a message */
4543                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4544
4545                         TnyHeader *header = NULL;
4546                         header = modest_msg_view_window_get_header
4547                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4548                         if (!TNY_IS_HEADER(header))
4549                                 g_warning ("%s: could not get source header", __FUNCTION__);
4550                         else
4551                                 src_folder = tny_header_get_folder (header);
4552
4553                         if (header)
4554                                 g_object_unref (header);
4555                 } else {
4556                         src_folder = 
4557                                 TNY_FOLDER (modest_folder_view_get_selected
4558                                             (MODEST_FOLDER_VIEW (folder_view)));
4559                 }
4560
4561                 if (TNY_IS_FOLDER(src_folder)) {
4562                         /* Do not allow to move the msg to the same folder */
4563                         /* Do not allow to move the msg to an account */
4564                         if ((gpointer) src_folder == (gpointer) folder_store ||
4565                             TNY_IS_ACCOUNT (folder_store))
4566                                 ok_sensitive = FALSE;
4567                         g_object_unref (src_folder);
4568                 } else
4569                         g_warning ("%s: could not get source folder", __FUNCTION__);
4570         }
4571
4572  end:
4573         /* Set sensitivity of the OK button */
4574         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4575         /* Set sensitivity of the NEW button */
4576         gtk_widget_set_sensitive (new_button, new_sensitive);
4577 }
4578
4579
4580 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4581
4582 static GtkWidget*
4583 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4584 {
4585         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4586                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4587 }
4588
4589 static GtkWidget*
4590 create_move_to_dialog (GtkWindow *win,
4591                        GtkWidget *folder_view,
4592                        GtkWidget **tree_view)
4593 {
4594         GtkWidget *dialog, *scroll;
4595         GtkWidget *new_button;
4596
4597         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4598                                               GTK_WINDOW (win),
4599                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4600                                               NULL);
4601
4602 #ifdef MODEST_PLATFORM_MAEMO
4603         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4604         /* We do this manually so GTK+ does not associate a response ID for
4605          * the button. */
4606         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4607         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4608         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4609 #else
4610         /* We do this manually so GTK+ does not associate a response ID for
4611          * the button. */
4612         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4613         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4614         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4615         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4616         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4617         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4618         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4619 #endif
4620
4621         /* Create scrolled window */
4622         scroll = gtk_scrolled_window_new (NULL, NULL);
4623         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4624                                          GTK_POLICY_AUTOMATIC,
4625                                          GTK_POLICY_AUTOMATIC);
4626
4627 #ifndef MODEST_PLATFORM_MAEMO
4628         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4629 #endif
4630
4631         /* Create folder view */
4632         *tree_view = modest_platform_create_folder_view (NULL);
4633
4634         /* Track changes in the selection to
4635          * disable the OK button whenever "Move to" is not possible
4636          * disbale NEW button whenever New is not possible */
4637         g_signal_connect (*tree_view,
4638                           "folder_selection_changed",
4639                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4640                           win);
4641
4642         /* Listen to clicks on New button */
4643         g_signal_connect (G_OBJECT (new_button), 
4644                           "clicked", 
4645                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4646                           *tree_view);
4647
4648         /* It could happen that we're trying to move a message from a
4649            window (msg window for example) after the main window was
4650            closed, so we can not just get the model of the folder
4651            view */
4652         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4653                 const gchar *visible_id = NULL;
4654
4655                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4656                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4657                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4658                                                MODEST_FOLDER_VIEW(*tree_view));
4659
4660                 visible_id = 
4661                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4662
4663                 /* Show the same account than the one that is shown in the main window */
4664                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4665                                                                              visible_id);
4666         } else {
4667                 const gchar *active_account_name = NULL;
4668                 ModestAccountMgr *mgr = NULL;
4669                 ModestAccountSettings *settings = NULL;
4670                 ModestServerAccountSettings *store_settings = NULL;
4671
4672                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4673                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4674                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4675                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4676
4677                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4678                 mgr = modest_runtime_get_account_mgr ();
4679                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4680
4681                 if (settings) {
4682                         const gchar *store_account_name;
4683                         store_settings = modest_account_settings_get_store_settings (settings);
4684                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4685
4686                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4687                                                                                      store_account_name);
4688                         g_object_unref (store_settings);
4689                         g_object_unref (settings);
4690                 }
4691         }
4692
4693         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4694          *   get_folder_view_from_move_to_dialog 
4695          * (see above) later (needed for focus handling) 
4696          */
4697         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4698
4699         
4700         /* Hide special folders */
4701         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4702
4703         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4704
4705         /* Add scroll to dialog */
4706         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4707                             scroll, TRUE, TRUE, 0);
4708
4709         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4710 #ifdef MODEST_PLATFORM_MAEMO
4711         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4712 #else
4713         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4714 #endif
4715
4716         return dialog;
4717 }
4718
4719
4720
4721 /*
4722  * Shows a confirmation dialog to the user when we're moving messages
4723  * from a remote server to the local storage. Returns the dialog
4724  * response. If it's other kind of movement then it always returns
4725  * GTK_RESPONSE_OK
4726  *
4727  * This one is used by the next functions:
4728  *      modest_ui_actions_on_paste                      - commented out
4729  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4730  */
4731 gint
4732 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4733                                              TnyFolder *dest_folder,
4734                                              gboolean delete,
4735                                              TnyList *headers)
4736 {
4737         gint response = GTK_RESPONSE_OK;
4738         TnyAccount *account = NULL;
4739         TnyFolder *src_folder = NULL;
4740         TnyIterator *iter = NULL;
4741         TnyHeader *header = NULL;
4742
4743         /* return with OK if the destination is a remote folder */
4744         if (modest_tny_folder_is_remote_folder (dest_folder))
4745                 return GTK_RESPONSE_OK;
4746
4747         /* Get source folder */
4748         iter = tny_list_create_iterator (headers);
4749         header = TNY_HEADER (tny_iterator_get_current (iter));
4750         if (header) {
4751                 src_folder = tny_header_get_folder (header);
4752                 g_object_unref (header);
4753         }
4754         g_object_unref (iter);
4755
4756         /* if no src_folder, message may be an attahcment */
4757         if (src_folder == NULL) 
4758                 return GTK_RESPONSE_CANCEL;
4759
4760         /* If the source is a local or MMC folder */
4761         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4762                 g_object_unref (src_folder);
4763                 return GTK_RESPONSE_OK;
4764         }
4765
4766         /* Get the account */
4767         account = tny_folder_get_account (src_folder);
4768
4769         /* now if offline we ask the user */
4770         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4771                 response = GTK_RESPONSE_OK;
4772         else
4773                 response = GTK_RESPONSE_CANCEL;
4774
4775         /* Frees */
4776         g_object_unref (src_folder);
4777         g_object_unref (account);
4778
4779         return response;
4780 }
4781
4782 static void
4783 move_to_helper_destroyer (gpointer user_data)
4784 {
4785         MoveToHelper *helper = (MoveToHelper *) user_data;
4786
4787         /* Close the "Pasting" information banner */
4788         if (helper->banner) {
4789                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4790                 g_object_unref (helper->banner);
4791         }
4792         if (helper->reference != NULL)
4793                 gtk_tree_row_reference_free (helper->reference);
4794         g_free (helper);
4795 }
4796
4797 static void
4798 move_to_cb (ModestMailOperation *mail_op, 
4799             gpointer user_data)
4800 {
4801         MoveToHelper *helper = (MoveToHelper *) user_data;
4802
4803         /* Note that the operation could have failed, in that case do
4804            nothing */
4805         if (modest_mail_operation_get_status (mail_op) == 
4806             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4807
4808                 GObject *object = modest_mail_operation_get_source (mail_op);
4809                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4810                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4811
4812                         if (!modest_msg_view_window_select_next_message (self) &&
4813                             !modest_msg_view_window_select_previous_message (self)) {
4814                                 /* No more messages to view, so close this window */
4815                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4816                         }
4817                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4818                         GtkWidget *header_view;
4819                         GtkTreePath *path;
4820                         GtkTreeSelection *sel;
4821
4822                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4823                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4824                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4825                         path = gtk_tree_row_reference_get_path (helper->reference);
4826                         /* We need to unselect the previous one
4827                            because we could be copying instead of
4828                            moving */
4829                         gtk_tree_selection_unselect_all (sel);
4830                         gtk_tree_selection_select_path (sel, path);
4831                         gtk_tree_path_free (path);
4832                 }
4833                 g_object_unref (object);
4834         }
4835         /* Destroy the helper */
4836         move_to_helper_destroyer (helper);
4837 }
4838
4839 static void
4840 folder_move_to_cb (ModestMailOperation *mail_op, 
4841                    TnyFolder *new_folder,
4842                    gpointer user_data)
4843 {
4844         GtkWidget *folder_view;
4845         GObject *object;
4846
4847         object = modest_mail_operation_get_source (mail_op);
4848         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4849                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4850         g_object_ref (folder_view);
4851         g_object_unref (object);
4852         move_to_cb (mail_op, user_data);
4853         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4854         g_object_unref (folder_view);
4855 }
4856
4857 static void
4858 msgs_move_to_cb (ModestMailOperation *mail_op, 
4859                  gpointer user_data)
4860 {
4861         move_to_cb (mail_op, user_data);
4862 }
4863
4864 void
4865 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4866                                              gpointer user_data)
4867 {
4868         ModestWindow *main_window = NULL;
4869         
4870         /* Disable next automatic folder selection */
4871         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4872                                                          FALSE); /* don't create */
4873         if (main_window) {
4874                 GObject *win = NULL;
4875                 GtkWidget *folder_view = NULL;
4876         
4877                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4878                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4879                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4880                 
4881                 if (user_data && TNY_IS_FOLDER (user_data)) {
4882                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4883                                                           TNY_FOLDER (user_data), FALSE);
4884                 }
4885
4886                 /* Show notification dialog only if the main window exists */
4887                 win = modest_mail_operation_get_source (mail_op);
4888                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4889                                                         _("mail_in_ui_folder_move_target_error"), 
4890                                                         FALSE);
4891                 if (win)
4892                         g_object_unref (win);
4893         }
4894 }
4895
4896 static void
4897 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4898                        TnyHeader *header, 
4899                        gboolean canceled,
4900                        TnyMsg *msg, 
4901                        GError *err,
4902                        gpointer user_data)
4903 {
4904         TnyList *parts;
4905         TnyIterator *iter;
4906         gint pending_purges = 0;
4907         gboolean some_purged = FALSE;
4908         ModestWindow *win = MODEST_WINDOW (user_data);
4909         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4910
4911         /* If there was any error */
4912         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4913                 modest_window_mgr_unregister_header (mgr, header);
4914                 return;
4915         }
4916
4917         /* Once the message has been retrieved for purging, we check if
4918          * it's all ok for purging */
4919
4920         parts = tny_simple_list_new ();
4921         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4922         iter = tny_list_create_iterator (parts);
4923
4924         while (!tny_iterator_is_done (iter)) {
4925                 TnyMimePart *part;
4926                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4927                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4928                         if (tny_mime_part_is_purged (part))
4929                                 some_purged = TRUE;
4930                         else
4931                                 pending_purges++;
4932                 }
4933
4934                 if (part)
4935                         g_object_unref (part);
4936
4937                 tny_iterator_next (iter);
4938         }
4939         g_object_unref (iter);
4940         
4941
4942         if (pending_purges>0) {
4943                 gint response;
4944                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4945
4946                 if (response == GTK_RESPONSE_OK) {
4947                         GtkWidget *info;
4948                         info =
4949                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
4950                         iter = tny_list_create_iterator (parts);
4951                         while (!tny_iterator_is_done (iter)) {
4952                                 TnyMimePart *part;
4953                                 
4954                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4955                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4956                                         tny_mime_part_set_purged (part);
4957
4958                                 if (part)
4959                                         g_object_unref (part);
4960
4961                                 tny_iterator_next (iter);
4962                         }
4963                         g_object_unref (iter);
4964                         
4965                         tny_msg_rewrite_cache (msg);
4966
4967                         gtk_widget_destroy (info);
4968                 }
4969         }
4970
4971         modest_window_mgr_unregister_header (mgr, header);
4972
4973         g_object_unref (parts);
4974 }
4975
4976 static void
4977 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4978                                                      ModestMainWindow *win)
4979 {
4980         GtkWidget *header_view;
4981         TnyList *header_list;
4982         TnyHeader *header;
4983         TnyHeaderFlags flags;
4984         ModestWindow *msg_view_window =  NULL;
4985         gboolean found;
4986
4987         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4988
4989         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4990                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4991
4992         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4993         if (!header_list) {
4994                 g_warning ("%s: no header selected", __FUNCTION__);
4995                 return;
4996         }
4997         
4998         if (tny_list_get_length (header_list) == 1) {
4999                 TnyIterator *iter = tny_list_create_iterator (header_list);
5000                 header = TNY_HEADER (tny_iterator_get_current (iter));
5001                 g_object_unref (iter);
5002         } else
5003                 return;
5004         
5005         if (!header || !TNY_IS_HEADER(header)) {
5006                 g_warning ("%s: header is not valid", __FUNCTION__);
5007                 return;
5008         }
5009         
5010         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5011                                                           header, &msg_view_window);
5012         flags = tny_header_get_flags (header);
5013         if (!(flags & TNY_HEADER_FLAG_CACHED))
5014                 return;
5015         if (found) {
5016                 if (msg_view_window != NULL) 
5017                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5018                 else {
5019                         /* do nothing; uid was registered before, so window is probably on it's way */
5020                         g_warning ("debug: header %p has already been registered", header);
5021                 }
5022         } else {
5023                 ModestMailOperation *mail_op = NULL;
5024                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5025                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5026                                                                          modest_ui_actions_disk_operations_error_handler,
5027                                                                          NULL, NULL);
5028                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5029                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5030                 
5031                 g_object_unref (mail_op);
5032         }
5033         if (header)
5034                 g_object_unref (header);
5035         if (header_list)
5036                 g_object_unref (header_list);
5037 }
5038
5039 /*
5040  * Checks if we need a connection to do the transfer and if the user
5041  * wants to connect to complete it
5042  */
5043 void
5044 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5045                                        TnyFolderStore *src_folder,
5046                                        TnyList *headers,
5047                                        TnyFolder *dst_folder,
5048                                        gboolean delete_originals,
5049                                        gboolean *need_connection,
5050                                        gboolean *do_xfer)
5051 {
5052         TnyAccount *src_account;
5053         gint uncached_msgs = 0;
5054
5055         uncached_msgs = header_list_count_uncached_msgs (headers);
5056
5057         /* We don't need any further check if
5058          *
5059          * 1- the source folder is local OR
5060          * 2- the device is already online
5061          */
5062         if (!modest_tny_folder_store_is_remote (src_folder) ||
5063             tny_device_is_online (modest_runtime_get_device())) {
5064                 *need_connection = FALSE;
5065                 *do_xfer = TRUE;
5066                 return;
5067         }
5068
5069         /* We must ask for a connection when
5070          *
5071          *   - the message(s) is not already cached   OR 
5072          *   - the message(s) is cached but the leave_on_server setting
5073          * is FALSE (because we need to sync the source folder to
5074          * delete the message from the server (for IMAP we could do it
5075          * offline, it'll take place the next time we get a
5076          * connection)
5077          */
5078         src_account = get_account_from_folder_store (src_folder);
5079         if (uncached_msgs > 0) {
5080                 guint num_headers;
5081                 const gchar *msg;
5082
5083                 *need_connection = TRUE;
5084                 num_headers = tny_list_get_length (headers);
5085                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5086
5087                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5088                     GTK_RESPONSE_CANCEL) {
5089                         *do_xfer = FALSE;
5090                 } else {
5091                         *do_xfer = TRUE;
5092                 }
5093         } else {
5094                 /* The transfer is possible and the user wants to */
5095                 *do_xfer = TRUE;
5096
5097                 if (remote_folder_is_pop (src_folder) && delete_originals) {
5098                         const gchar *account_name;
5099                         gboolean leave_on_server;
5100                         
5101                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5102                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5103                                                                                   account_name);
5104                         
5105                         if (leave_on_server == TRUE) {
5106                                 *need_connection = FALSE;
5107                         } else {
5108                                 *need_connection = TRUE;
5109                         }
5110                 } else {
5111                         *need_connection = FALSE;
5112                 }
5113         }
5114
5115         /* Frees */
5116         g_object_unref (src_account);
5117 }
5118
5119 static void
5120 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5121                              gpointer user_data)
5122 {
5123         ModestWindow *main_window = NULL;
5124
5125         /* Disable next automatic folder selection */
5126         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5127                                                          FALSE); /* don't create */
5128         if (main_window) {
5129                 GObject *win = modest_mail_operation_get_source (mail_op);
5130                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5131                                                         _("mail_in_ui_folder_move_target_error"), 
5132                                                         FALSE);
5133                 if (win)
5134                         g_object_unref (win);
5135         }
5136         move_to_helper_destroyer (user_data);
5137 }
5138
5139 typedef struct {
5140         TnyFolderStore *dst_folder;
5141         TnyList *headers;
5142 } XferMsgsHelper;
5143
5144 /**
5145  * Utility function that transfer messages from both the main window
5146  * and the msg view window when using the "Move to" dialog
5147  */
5148 static void
5149 xfer_messages_performer  (gboolean canceled, 
5150                           GError *err,
5151                           GtkWindow *parent_window, 
5152                           TnyAccount *account, 
5153                           gpointer user_data)
5154 {
5155         ModestWindow *win = MODEST_WINDOW (parent_window);
5156         TnyAccount *dst_account = NULL;
5157         const gchar *proto_str = NULL;
5158         gboolean dst_is_pop = FALSE;
5159         XferMsgsHelper *helper;
5160         MoveToHelper *movehelper;
5161         ModestMailOperation *mail_op;
5162
5163         helper = (XferMsgsHelper *) user_data;
5164
5165         if (canceled || err) {
5166                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5167                         /* Show the proper error message */
5168                         modest_ui_actions_on_account_connection_error (parent_window, account);
5169                 }
5170                 goto end;
5171         }
5172
5173         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5174         proto_str = tny_account_get_proto (dst_account);
5175
5176         /* tinymail will return NULL for local folders it seems */
5177         dst_is_pop = proto_str &&
5178                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
5179                  MODEST_PROTOCOL_STORE_POP);
5180
5181         g_object_unref (dst_account);
5182
5183         if (dst_is_pop) {
5184                 modest_platform_information_banner (GTK_WIDGET (win),
5185                                                     NULL,
5186                                                     ngettext("mail_in_ui_folder_move_target_error",
5187                                                              "mail_in_ui_folder_move_targets_error",
5188                                                              tny_list_get_length (helper->headers)));
5189                 goto end;
5190         }
5191
5192         movehelper = g_new0 (MoveToHelper, 1);
5193         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5194                                                                _CS("ckct_nw_pasting"));
5195         if (movehelper->banner != NULL)  {
5196                 g_object_ref (movehelper->banner);
5197                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5198         }
5199
5200         if (MODEST_IS_MAIN_WINDOW (win)) {
5201                 GtkWidget *header_view = 
5202                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5203                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5204                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5205         }
5206
5207         /* Perform the mail operation */
5208         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5209                                                                  xfer_messages_error_handler,
5210                                                                  movehelper, NULL);
5211         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5212                                          mail_op);
5213
5214         modest_mail_operation_xfer_msgs (mail_op, 
5215                                          helper->headers,
5216                                          TNY_FOLDER (helper->dst_folder),
5217                                          TRUE,
5218                                          msgs_move_to_cb,
5219                                          movehelper);
5220
5221         g_object_unref (G_OBJECT (mail_op));
5222  end:
5223         g_object_unref (helper->dst_folder);
5224         g_object_unref (helper->headers);
5225         g_slice_free (XferMsgsHelper, helper);
5226 }
5227
5228 typedef struct {
5229         TnyFolder *src_folder;
5230         TnyFolderStore *dst_folder;
5231         gboolean delete_original;
5232         GtkWidget *folder_view;
5233 } MoveFolderInfo;
5234
5235 static void
5236 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5237                 TnyAccount *account, gpointer user_data)
5238 {
5239         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5240         GtkTreeSelection *sel;
5241         ModestMailOperation *mail_op = NULL;
5242         
5243         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5244                 g_object_unref (G_OBJECT (info->src_folder));
5245                 g_object_unref (G_OBJECT (info->dst_folder));
5246                 g_free (info);
5247                 return;
5248         }
5249         
5250         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5251         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5252                         _CS("ckct_nw_pasting"));
5253         if (helper->banner != NULL)  {
5254                 g_object_ref (helper->banner);
5255                 gtk_widget_show (GTK_WIDGET(helper->banner));
5256         }
5257         /* Clean folder on header view before moving it */
5258         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5259         gtk_tree_selection_unselect_all (sel);
5260
5261         /* Let gtk events run. We need that the folder
5262            view frees its reference to the source
5263            folder *before* issuing the mail operation
5264            so we need the signal handler of selection
5265            changed to happen before the mail
5266            operation 
5267         while (gtk_events_pending ())
5268                 gtk_main_iteration ();   */
5269
5270         mail_op =
5271                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5272                                 modest_ui_actions_move_folder_error_handler,
5273                                 info->src_folder, NULL);
5274         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5275                         mail_op);
5276
5277         /* Select *after* the changes */
5278         /* TODO: this function hangs UI after transfer */ 
5279         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5280         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5281
5282         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5283                                           TNY_FOLDER (info->dst_folder), TRUE);
5284         modest_mail_operation_xfer_folder (mail_op,
5285                         TNY_FOLDER (info->src_folder),
5286                         info->dst_folder,
5287                         info->delete_original, 
5288                         folder_move_to_cb, 
5289                         helper);
5290         g_object_unref (G_OBJECT (info->src_folder));
5291
5292         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5293         /* } */
5294         
5295         /* Unref mail operation */
5296         g_object_unref (G_OBJECT (mail_op));
5297         g_object_unref (G_OBJECT (info->dst_folder));
5298         g_free (user_data);
5299 }
5300
5301 static TnyAccount *
5302 get_account_from_folder_store (TnyFolderStore *folder_store) 
5303 {
5304         if (TNY_IS_ACCOUNT (folder_store))
5305                 return g_object_ref (folder_store);
5306         else
5307                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5308 }
5309
5310 /*
5311  * UI handler for the "Move to" action when invoked from the
5312  * ModestMainWindow
5313  */
5314 static void 
5315 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5316                                           GtkWidget *folder_view,
5317                                           TnyFolderStore *dst_folder,
5318                                           ModestMainWindow *win)
5319 {
5320         ModestHeaderView *header_view = NULL;
5321         TnyFolderStore *src_folder = NULL;
5322
5323         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5324
5325         /* Get the source folder */
5326         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5327
5328         /* Get header view */
5329         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5330
5331         /* Get folder or messages to transfer */
5332         if (gtk_widget_is_focus (folder_view)) {
5333                 gboolean do_xfer = TRUE;
5334
5335                 /* Allow only to transfer folders to the local root folder */
5336                 if (TNY_IS_ACCOUNT (dst_folder) && 
5337                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5338                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5339                         do_xfer = FALSE;
5340                 } else if (!TNY_IS_FOLDER (src_folder)) {
5341                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5342                         do_xfer = FALSE;
5343                 }
5344
5345                 if (do_xfer) {                  
5346                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5347                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5348
5349                         info->src_folder = g_object_ref (src_folder);
5350                         info->dst_folder = g_object_ref (dst_folder);
5351                         info->delete_original = TRUE;
5352                         info->folder_view = folder_view;
5353
5354                         connect_info->callback = on_move_folder_cb;
5355                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5356                         connect_info->data = info;
5357
5358                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5359                                                                    TNY_FOLDER_STORE (src_folder), 
5360                                                                    connect_info);
5361                 }
5362         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5363                 TnyList *headers;
5364
5365                 headers = modest_header_view_get_selected_headers(header_view);
5366
5367                 /* Transfer the messages */
5368                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5369                                                             headers, TNY_FOLDER (dst_folder));
5370
5371                 g_object_unref (headers);
5372         }
5373
5374         /* Frees */
5375         g_object_unref (src_folder);
5376 }
5377
5378
5379 void
5380 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5381                                             TnyFolder *src_folder,
5382                                             TnyList *headers,
5383                                             TnyFolder *dst_folder)
5384 {
5385         gboolean need_connection = TRUE;
5386         gboolean do_xfer = TRUE;
5387         XferMsgsHelper *helper;
5388         
5389         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5390                                                headers, TNY_FOLDER (dst_folder),
5391                                                TRUE, &need_connection, 
5392                                                &do_xfer);
5393
5394         /* If we don't want to transfer just return */
5395         if (!do_xfer)
5396                 return;
5397
5398         /* Create the helper */
5399         helper = g_slice_new (XferMsgsHelper);
5400         helper->dst_folder = g_object_ref (dst_folder);
5401         helper->headers = g_object_ref (headers);
5402
5403         if (need_connection) {
5404                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5405                 connect_info->callback = xfer_messages_performer;
5406                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5407                 connect_info->data = helper;
5408                 
5409                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5410                                                            TNY_FOLDER_STORE (src_folder), 
5411                                                            connect_info);
5412         } else {
5413                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5414                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5415                                          src_account, helper);
5416                 g_object_unref (src_account);
5417         }
5418 }
5419
5420 /*
5421  * UI handler for the "Move to" action when invoked from the
5422  * ModestMsgViewWindow
5423  */
5424 static void 
5425 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5426                                               TnyFolderStore *dst_folder,
5427                                               ModestMsgViewWindow *win)
5428 {
5429         TnyList *headers = NULL;
5430         TnyHeader *header = NULL;
5431         TnyFolder *src_folder = NULL;
5432
5433         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5434
5435         /* Create header list */
5436         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5437         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5438         headers = tny_simple_list_new ();
5439         tny_list_append (headers, G_OBJECT (header));
5440
5441         /* Transfer the messages */
5442         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5443                                                     TNY_FOLDER (dst_folder));
5444
5445         /* Frees */
5446         g_object_unref (header);
5447         g_object_unref (headers);
5448 }
5449
5450 void 
5451 modest_ui_actions_on_move_to (GtkAction *action, 
5452                               ModestWindow *win)
5453 {
5454         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5455         gint result = 0;
5456         TnyFolderStore *dst_folder = NULL;
5457         ModestMainWindow *main_window;
5458
5459         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5460                           MODEST_IS_MSG_VIEW_WINDOW (win));
5461
5462         /* Get the main window if exists */
5463         if (MODEST_IS_MAIN_WINDOW (win))
5464                 main_window = MODEST_MAIN_WINDOW (win);
5465         else
5466                 main_window = 
5467                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5468                                                                                FALSE)); /* don't create */
5469
5470         /* Get the folder view widget if exists */
5471         if (main_window)
5472                 folder_view = modest_main_window_get_child_widget (main_window,
5473                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5474         else
5475                 folder_view = NULL;
5476
5477         /* Create and run the dialog */
5478         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5479         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5480         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
5481         result = gtk_dialog_run (GTK_DIALOG(dialog));
5482         g_object_ref (tree_view);
5483         gtk_widget_destroy (dialog);
5484
5485         if (result != GTK_RESPONSE_ACCEPT)
5486                 return;
5487
5488         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5489         /* Do window specific stuff */
5490         if (MODEST_IS_MAIN_WINDOW (win)) {
5491                 modest_ui_actions_on_main_window_move_to (action,
5492                                 folder_view,
5493                                 dst_folder,
5494                                 MODEST_MAIN_WINDOW (win));
5495         } else {
5496                 modest_ui_actions_on_msg_view_window_move_to (action,
5497                                 dst_folder,
5498                                 MODEST_MSG_VIEW_WINDOW (win));
5499         }
5500
5501         if (dst_folder)
5502                 g_object_unref (dst_folder);
5503 }
5504
5505 /*
5506  * Calls #HeadersFunc for each header already selected in the main
5507  * window or the message currently being shown in the msg view window
5508  */
5509 static void
5510 do_headers_action (ModestWindow *win, 
5511                    HeadersFunc func,
5512                    gpointer user_data)
5513 {
5514         TnyList *headers_list = NULL;
5515         TnyIterator *iter = NULL;
5516         TnyHeader *header = NULL;
5517         TnyFolder *folder = NULL;
5518
5519         /* Get headers */
5520         headers_list = get_selected_headers (win);
5521         if (!headers_list)
5522                 return;
5523
5524         /* Get the folder */
5525         iter = tny_list_create_iterator (headers_list);
5526         header = TNY_HEADER (tny_iterator_get_current (iter));
5527         if (header) {
5528                 folder = tny_header_get_folder (header);
5529                 g_object_unref (header);
5530         }
5531
5532         /* Call the function for each header */
5533         while (!tny_iterator_is_done (iter)) {
5534                 header = TNY_HEADER (tny_iterator_get_current (iter));
5535                 func (header, win, user_data);
5536                 g_object_unref (header);
5537                 tny_iterator_next (iter);
5538         }
5539
5540         /* Trick: do a poke status in order to speed up the signaling
5541            of observers */
5542         tny_folder_poke_status (folder);
5543
5544         /* Frees */
5545         g_object_unref (folder);
5546         g_object_unref (iter);
5547         g_object_unref (headers_list);
5548 }
5549
5550 void 
5551 modest_ui_actions_view_attachment (GtkAction *action,
5552                                    ModestWindow *window)
5553 {
5554         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5555                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5556         } else {
5557                 /* not supported window for this action */
5558                 g_return_if_reached ();
5559         }
5560 }
5561
5562 void
5563 modest_ui_actions_save_attachments (GtkAction *action,
5564                                     ModestWindow *window)
5565 {
5566         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5567
5568                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5569                         return;
5570
5571                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5572         } else {
5573                 /* not supported window for this action */
5574                 g_return_if_reached ();
5575         }
5576 }
5577
5578 void
5579 modest_ui_actions_remove_attachments (GtkAction *action,
5580                                       ModestWindow *window)
5581 {
5582         if (MODEST_IS_MAIN_WINDOW (window)) {
5583                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5584         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5585                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5586         } else {
5587                 /* not supported window for this action */
5588                 g_return_if_reached ();
5589         }
5590 }
5591
5592 void 
5593 modest_ui_actions_on_settings (GtkAction *action, 
5594                                ModestWindow *win)
5595 {
5596         GtkWidget *dialog;
5597
5598         dialog = modest_platform_get_global_settings_dialog ();
5599         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5600         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5601         gtk_widget_show_all (dialog);
5602
5603         gtk_dialog_run (GTK_DIALOG (dialog));
5604
5605         gtk_widget_destroy (dialog);
5606 }
5607
5608 void 
5609 modest_ui_actions_on_help (GtkAction *action, 
5610                            GtkWindow *win)
5611 {
5612         const gchar *help_id;
5613
5614         g_return_if_fail (win && GTK_IS_WINDOW(win));
5615         
5616         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5617
5618         if (help_id)
5619                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5620 }
5621
5622 void 
5623 modest_ui_actions_on_csm_help (GtkAction *action, 
5624                                GtkWindow *win)
5625 {
5626         const gchar* help_id = NULL;
5627         GtkWidget *folder_view;
5628         TnyFolderStore *folder_store;
5629
5630         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5631
5632         /* Get selected folder */
5633         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5634                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5635         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5636
5637         /* Switch help_id */
5638         if (folder_store && TNY_IS_FOLDER (folder_store))
5639                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5640
5641         if (folder_store)
5642                 g_object_unref (folder_store);
5643
5644         if (help_id)
5645                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5646         else
5647                 modest_ui_actions_on_help (action, win);
5648 }
5649
5650 static void     
5651 retrieve_contents_cb (ModestMailOperation *mail_op, 
5652                       TnyHeader *header, 
5653                       gboolean canceled,
5654                       TnyMsg *msg,
5655                       GError *err,
5656                       gpointer user_data)
5657 {
5658         /* We only need this callback to show an error in case of
5659            memory low condition */
5660         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5661 }
5662
5663 static void
5664 retrieve_msg_contents_performer (gboolean canceled, 
5665                                  GError *err,
5666                                  GtkWindow *parent_window, 
5667                                  TnyAccount *account, 
5668                                  gpointer user_data)
5669 {
5670         ModestMailOperation *mail_op;
5671         TnyList *headers = TNY_LIST (user_data);
5672
5673         if (err || canceled) {
5674                 check_memory_full_error ((GtkWidget *) parent_window, err);
5675                 goto out;
5676         }
5677
5678         /* Create mail operation */
5679         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5680                                                                  modest_ui_actions_disk_operations_error_handler, 
5681                                                                  NULL, NULL);
5682         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5683         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5684
5685         /* Frees */
5686         g_object_unref (mail_op);
5687  out:
5688         g_object_unref (headers);
5689         g_object_unref (account);
5690 }
5691
5692 void 
5693 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5694                                             ModestWindow *window)
5695 {
5696         TnyList *headers = NULL;
5697         TnyAccount *account = NULL;
5698         TnyIterator *iter = NULL;
5699         TnyHeader *header = NULL;
5700         TnyFolder *folder = NULL;
5701
5702         /* Get headers */
5703         headers = get_selected_headers (window);
5704         if (!headers)
5705                 return;
5706
5707         /* Pick the account */
5708         iter = tny_list_create_iterator (headers);
5709         header = TNY_HEADER (tny_iterator_get_current (iter));
5710         folder = tny_header_get_folder (header);
5711         account = tny_folder_get_account (folder);
5712         g_object_unref (folder);
5713         g_object_unref (header);
5714         g_object_unref (iter);
5715
5716         /* Connect and perform the message retrieval */
5717         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5718                                              g_object_ref (account), 
5719                                              retrieve_msg_contents_performer, 
5720                                              g_object_ref (headers));
5721
5722         /* Frees */
5723         g_object_unref (account);
5724         g_object_unref (headers);
5725 }
5726
5727 void
5728 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5729 {
5730         g_return_if_fail (MODEST_IS_WINDOW (window));
5731
5732         /* Update dimmed */
5733         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5734 }
5735
5736 void
5737 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5738 {
5739         g_return_if_fail (MODEST_IS_WINDOW (window));
5740
5741         /* Update dimmed */
5742         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5743 }
5744
5745 void
5746 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5747                                           ModestWindow *window)
5748 {
5749         g_return_if_fail (MODEST_IS_WINDOW (window));
5750         
5751         /* Update dimmed */
5752         modest_ui_actions_check_menu_dimming_rules (window);
5753 }
5754
5755 void
5756 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5757                                           ModestWindow *window)
5758 {
5759         g_return_if_fail (MODEST_IS_WINDOW (window));
5760
5761         /* Update dimmed */
5762         modest_ui_actions_check_menu_dimming_rules (window);
5763 }
5764
5765 void
5766 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5767                                           ModestWindow *window)
5768 {
5769         g_return_if_fail (MODEST_IS_WINDOW (window));
5770
5771         /* Update dimmed */
5772         modest_ui_actions_check_menu_dimming_rules (window);
5773 }
5774
5775 void
5776 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5777                                             ModestWindow *window)
5778 {
5779         g_return_if_fail (MODEST_IS_WINDOW (window));
5780
5781         /* Update dimmed */
5782         modest_ui_actions_check_menu_dimming_rules (window);
5783 }
5784
5785 void
5786 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5787                                           ModestWindow *window)
5788 {
5789         g_return_if_fail (MODEST_IS_WINDOW (window));
5790
5791         /* Update dimmed */
5792         modest_ui_actions_check_menu_dimming_rules (window);
5793 }
5794
5795 void
5796 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5797                                           ModestWindow *window)
5798 {
5799         g_return_if_fail (MODEST_IS_WINDOW (window));
5800
5801         /* Update dimmed */
5802         modest_ui_actions_check_menu_dimming_rules (window);
5803 }
5804
5805 void
5806 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5807                                                  ModestWindow *window)
5808 {
5809         g_return_if_fail (MODEST_IS_WINDOW (window));
5810
5811         /* Update dimmed */
5812         modest_ui_actions_check_menu_dimming_rules (window);
5813 }
5814
5815 void
5816 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5817                                                      ModestWindow *window)
5818 {
5819         g_return_if_fail (MODEST_IS_WINDOW (window));
5820
5821         /* Update dimmed */
5822         modest_ui_actions_check_menu_dimming_rules (window);
5823 }
5824
5825 void
5826 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5827                                                      ModestWindow *window)
5828 {
5829         g_return_if_fail (MODEST_IS_WINDOW (window));
5830
5831         /* Update dimmed */
5832         modest_ui_actions_check_menu_dimming_rules (window);
5833 }
5834
5835 void
5836 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5837 {
5838         g_return_if_fail (MODEST_IS_WINDOW (window));
5839
5840         /* we check for low-mem; in that case, show a warning, and don't allow
5841          * searching
5842          */
5843         if (modest_platform_check_memory_low (window, TRUE))
5844                 return;
5845         
5846         modest_platform_show_search_messages (GTK_WINDOW (window));
5847 }
5848
5849 void     
5850 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5851 {
5852         g_return_if_fail (MODEST_IS_WINDOW (win));
5853
5854
5855         /* we check for low-mem; in that case, show a warning, and don't allow
5856          * for the addressbook
5857          */
5858         if (modest_platform_check_memory_low (win, TRUE))
5859                 return;
5860
5861
5862         modest_platform_show_addressbook (GTK_WINDOW (win));
5863 }
5864
5865
5866 void
5867 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5868                                           ModestWindow *window)
5869 {
5870         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5871
5872         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5873 }
5874
5875 static void 
5876 on_send_receive_finished (ModestMailOperation  *mail_op, 
5877                            gpointer user_data)
5878 {
5879         GtkWidget *header_view, *folder_view;
5880         TnyFolderStore *folder_store;
5881         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5882
5883         /* Set send/receive operation finished */       
5884         modest_main_window_notify_send_receive_completed (main_win);
5885
5886         /* Don't refresh the current folder if there were any errors */
5887         if (modest_mail_operation_get_status (mail_op) !=
5888             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5889                 return;
5890         
5891         /* Refresh the current folder if we're viewing a window. We do
5892            this because the user won't be able to see the new mails in
5893            the selected folder after a Send&Receive because it only
5894            performs a poke_status, i.e, only the number of read/unread
5895            messages is updated, but the new headers are not
5896            downloaded */
5897         folder_view = modest_main_window_get_child_widget (main_win, 
5898                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5899         if (!folder_view)
5900                 return;
5901
5902         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5903         
5904         /* Do not need to refresh INBOX again because the
5905            update_account does it always automatically */
5906         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5907             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5908                 ModestMailOperation *refresh_op;
5909
5910                 header_view = modest_main_window_get_child_widget (main_win,
5911                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5912                 
5913                 /* We do not need to set the contents style
5914                    because it hasn't changed. We also do not
5915                    need to save the widget status. Just force
5916                    a refresh */
5917                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5918                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5919                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5920                                                       folder_refreshed_cb, main_win);
5921                 g_object_unref (refresh_op);
5922         }
5923         
5924         if (folder_store)
5925                 g_object_unref (folder_store);
5926 }
5927
5928
5929 void 
5930 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5931                                                 TnyHeader *header, 
5932                                                 TnyMsg *msg, 
5933                                                 GError *err, 
5934                                                 gpointer user_data)
5935 {
5936         const gchar* server_name = NULL;
5937         TnyTransportAccount *server_account;
5938         gchar *message = NULL;
5939
5940         /* Don't show anything if the user cancelled something or the
5941          * send receive request is not interactive. Authentication
5942          * errors are managed by the account store so no need to show
5943          * a dialog here again */
5944         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5945             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
5946             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5947                 return;
5948
5949
5950         /* Get the server name: */
5951         server_account = 
5952                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5953         if (server_account)
5954                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
5955         else
5956                 g_return_if_reached ();
5957
5958         /* Show the appropriate message text for the GError: */
5959         switch (err->code) {
5960         case TNY_SERVICE_ERROR_CONNECT:
5961                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5962                 break;
5963         case TNY_SERVICE_ERROR_SEND:
5964                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5965                 break;
5966         case TNY_SERVICE_ERROR_UNAVAILABLE:
5967                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5968                 break;
5969         default:
5970                 g_warning ("%s: unexpected ERROR %d",
5971                            __FUNCTION__, err->code);
5972                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5973                 break;  
5974         }
5975
5976         modest_platform_run_information_dialog (NULL, message, FALSE);
5977         g_free (message);
5978         g_object_unref (server_account);
5979 }
5980
5981 void
5982 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5983                                                 gchar *msg_id, 
5984                                                 guint status,
5985                                                 gpointer user_data)
5986 {
5987         ModestMainWindow *main_window = NULL;
5988         ModestWindowMgr *mgr = NULL;
5989         GtkWidget *folder_view = NULL, *header_view = NULL;
5990         TnyFolderStore *selected_folder = NULL;
5991         TnyFolderType folder_type;
5992
5993         mgr = modest_runtime_get_window_mgr ();
5994         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5995                                                                              FALSE));/* don't create */
5996         if (!main_window)
5997                 return;
5998
5999         /* Check if selected folder is OUTBOX */
6000         folder_view = modest_main_window_get_child_widget (main_window,
6001                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6002         header_view = modest_main_window_get_child_widget (main_window,
6003                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6004
6005         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6006         if (!TNY_IS_FOLDER (selected_folder)) 
6007                 goto frees;
6008
6009         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6010 #if GTK_CHECK_VERSION(2, 8, 0) 
6011         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6012         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6013                 GtkTreeViewColumn *tree_column;
6014
6015                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6016                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6017                 gtk_tree_view_column_queue_resize (tree_column);
6018         }
6019 #else
6020         gtk_widget_queue_draw (header_view);
6021 #endif          
6022
6023         /* Rerun dimming rules, because the message could become deletable for example */
6024         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6025                                                  MODEST_DIMMING_RULES_TOOLBAR);
6026         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6027                                                  MODEST_DIMMING_RULES_MENU);
6028         
6029         /* Free */
6030  frees:
6031         if (selected_folder != NULL)
6032                 g_object_unref (selected_folder);
6033 }
6034
6035 void 
6036 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6037                                                TnyAccount *account)
6038 {
6039         ModestTransportStoreProtocol proto;
6040         const gchar *proto_name;
6041         gchar *error_note = NULL;
6042         
6043         proto_name = tny_account_get_proto (account);
6044         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
6045         
6046         switch (proto) {
6047         case MODEST_PROTOCOL_STORE_POP:
6048                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
6049                                               tny_account_get_hostname (account));
6050                 break;
6051         case MODEST_PROTOCOL_STORE_IMAP:
6052                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
6053                                               tny_account_get_hostname (account));
6054                 break;
6055         case MODEST_PROTOCOL_STORE_MAILDIR:
6056         case MODEST_PROTOCOL_STORE_MBOX:
6057                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
6058                 break;
6059         default:
6060                 g_warning ("%s: This should not be reached", __FUNCTION__);
6061         }
6062
6063         if (error_note) {
6064                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6065                 g_free (error_note);
6066         }
6067 }
6068
6069 gchar *
6070 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6071 {
6072         gchar *msg = NULL;
6073         TnyFolderStore *folder = NULL;
6074         TnyAccount *account = NULL;
6075         ModestTransportStoreProtocol proto;
6076         TnyHeader *header = NULL;
6077
6078         if (MODEST_IS_MAIN_WINDOW (win)) {
6079                 GtkWidget *header_view;
6080                 TnyList* headers = NULL;
6081                 TnyIterator *iter;
6082                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6083                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6084                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6085                 if (!headers || tny_list_get_length (headers) == 0) {
6086                         if (headers)
6087                                 g_object_unref (headers);
6088                         return NULL;
6089                 }
6090                 iter = tny_list_create_iterator (headers);
6091                 header = TNY_HEADER (tny_iterator_get_current (iter));
6092                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6093                 g_object_unref (iter);
6094                 g_object_unref (headers);
6095         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6096                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6097                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6098         }
6099
6100         /* Get the account type */
6101         account = tny_folder_get_account (TNY_FOLDER (folder));
6102         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
6103         if (proto == MODEST_PROTOCOL_STORE_POP) {
6104                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
6105         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
6106                 gchar *subject;
6107                 subject = tny_header_dup_subject (header);
6108                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
6109                                        subject);
6110                 g_free (subject);
6111         } else {
6112                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6113         }
6114
6115         /* Frees */
6116         g_object_unref (account);
6117         g_object_unref (folder);
6118         g_object_unref (header);
6119
6120         return msg;
6121 }