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