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