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