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