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