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