f9738a5febf0cfa4fcf20167f1c53b3c8fe238ac
[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         GtkWidget *dialog;
4279         
4280         /* Create dialog */
4281         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4282
4283         /* Run dialog */
4284         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) window);
4285         gtk_widget_show_all (dialog);
4286
4287         g_signal_connect_swapped (dialog, "response", 
4288                                   G_CALLBACK (gtk_widget_destroy),
4289                                   dialog);
4290 }
4291
4292 /*
4293  * Show the folder details in a ModestDetailsDialog widget
4294  */
4295 static void
4296 show_folder_details (TnyFolder *folder, 
4297                      GtkWindow *window)
4298 {
4299         GtkWidget *dialog;
4300         
4301         /* Create dialog */
4302         dialog = modest_details_dialog_new_with_folder (window, folder);
4303
4304         /* Run dialog */
4305         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4306         gtk_widget_show_all (dialog);
4307         gtk_dialog_run (GTK_DIALOG (dialog));
4308
4309         gtk_widget_destroy (dialog);
4310 }
4311
4312 /*
4313  * Show the header details in a ModestDetailsDialog widget
4314  */
4315 void     
4316 modest_ui_actions_on_details (GtkAction *action, 
4317                               ModestWindow *win)
4318 {
4319         TnyList * headers_list;
4320         TnyIterator *iter;
4321         TnyHeader *header;              
4322
4323         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4324                 TnyMsg *msg;
4325
4326                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4327                 if (!msg)
4328                         return;
4329                 g_object_unref (msg);           
4330
4331                 headers_list = get_selected_headers (win);
4332                 if (!headers_list)
4333                         return;
4334
4335                 iter = tny_list_create_iterator (headers_list);
4336
4337                 header = TNY_HEADER (tny_iterator_get_current (iter));
4338                 if (header) {
4339                         headers_action_show_details (header, win, NULL);
4340                         g_object_unref (header);
4341                 }
4342
4343                 g_object_unref (iter);
4344                 g_object_unref (headers_list);
4345
4346         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4347                 GtkWidget *folder_view, *header_view;
4348
4349                 /* Check which widget has the focus */
4350                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4351                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4352                 if (gtk_widget_is_focus (folder_view)) {
4353                         TnyFolderStore *folder_store
4354                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4355                         if (!folder_store) {
4356                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4357                                 return; 
4358                         }
4359                         /* Show only when it's a folder */
4360                         /* This function should not be called for account items, 
4361                          * because we dim the menu item for them. */
4362                         if (TNY_IS_FOLDER (folder_store)) {
4363                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4364                         }
4365
4366                         g_object_unref (folder_store);
4367
4368                 } else {
4369                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4370                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4371                         /* Show details of each header */
4372                         do_headers_action (win, headers_action_show_details, header_view);
4373                 }
4374         }
4375 }
4376
4377 void     
4378 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4379                                      ModestMsgEditWindow *window)
4380 {
4381         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4382
4383         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4384 }
4385
4386 void     
4387 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4388                                       ModestMsgEditWindow *window)
4389 {
4390         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4391
4392         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4393 }
4394
4395 void
4396 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4397                                        ModestMainWindow *main_window)
4398 {
4399         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4400
4401         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4402                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4403         else
4404                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4405 }
4406
4407 void 
4408 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4409                                      ModestWindow *window)
4410 {
4411         gboolean active, fullscreen = FALSE;
4412         ModestWindowMgr *mgr;
4413
4414         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4415
4416         /* Check if we want to toggle the toolbar vuew in fullscreen
4417            or normal mode */
4418         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4419                      "ViewShowToolbarFullScreen")) {
4420                 fullscreen = TRUE;
4421         }
4422
4423         /* Toggle toolbar */
4424         mgr = modest_runtime_get_window_mgr ();
4425         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4426 }
4427
4428 void     
4429 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4430                                            ModestMsgEditWindow *window)
4431 {
4432         modest_msg_edit_window_select_font (window);
4433 }
4434
4435
4436 void
4437 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4438                                                   const gchar *display_name,
4439                                                   GtkWindow *window)
4440 {
4441         /* don't update the display name if it was already set;
4442          * updating the display name apparently is expensive */
4443         const gchar* old_name = gtk_window_get_title (window);
4444
4445         if (display_name == NULL)
4446                 display_name = " ";
4447
4448         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4449                 return; /* don't do anything */
4450
4451         /* This is usually used to change the title of the main window, which
4452          * is the one that holds the folder view. Note that this change can
4453          * happen even when the widget doesn't have the focus. */
4454         gtk_window_set_title (window, display_name);
4455
4456 }
4457
4458 void
4459 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4460 {
4461         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4462         modest_msg_edit_window_select_contacts (window);
4463 }
4464
4465 void
4466 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4467 {
4468         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4469         modest_msg_edit_window_check_names (window, FALSE);
4470 }
4471
4472 static void
4473 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4474 {
4475         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4476                                          GTK_WIDGET (user_data));
4477 }
4478
4479 /*
4480  * This function is used to track changes in the selection of the
4481  * folder view that is inside the "move to" dialog to enable/disable
4482  * the OK button because we do not want the user to select a disallowed
4483  * destination for a folder.
4484  * The user also not desired to be able to use NEW button on items where
4485  * folder creation is not possibel.
4486  */
4487 static void
4488 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4489                                             TnyFolderStore *folder_store,
4490                                             gboolean selected,
4491                                             gpointer user_data)
4492 {
4493         GtkWidget *dialog = NULL;
4494         GtkWidget *ok_button = NULL, *new_button = NULL;
4495         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4496         gboolean moving_folder = FALSE;
4497         gboolean is_local_account = TRUE;
4498         GtkWidget *folder_view = NULL;
4499         ModestTnyFolderRules rules;
4500
4501         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4502         
4503         if (!selected)
4504                 return;
4505         
4506         /* Get the OK button */
4507         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4508         if (!dialog)
4509                 return;
4510
4511         ok_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON);
4512         new_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON);
4513
4514         /* check if folder_store is an remote account */
4515         if (TNY_IS_ACCOUNT (folder_store)) {
4516                 TnyAccount *local_account = NULL;
4517                 TnyAccount *mmc_account = NULL;
4518                 ModestTnyAccountStore *account_store = NULL;
4519
4520                 account_store = modest_runtime_get_account_store ();
4521                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4522                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4523
4524                 if ((gpointer) local_account != (gpointer) folder_store &&
4525                     (gpointer) mmc_account != (gpointer) folder_store) {
4526                         ModestProtocolType proto;
4527                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4528                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4529                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4530                         }
4531                         is_local_account = FALSE;
4532                         /* New button should be dimmed on remote
4533                            POP account root */
4534                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4535                                                                                          proto,
4536                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4537                 }
4538                 g_object_unref (local_account);
4539                 g_object_unref (mmc_account);
4540         }
4541
4542         /* Check the target folder rules */
4543         if (TNY_IS_FOLDER (folder_store)) {
4544                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4545                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4546                         ok_sensitive = FALSE;
4547                         new_sensitive = FALSE;
4548                         goto end;
4549                 }
4550         }
4551
4552         /* Check if we're moving a folder */
4553         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4554                 /* Get the widgets */
4555                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4556                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4557                 if (gtk_widget_is_focus (folder_view))
4558                         moving_folder = TRUE;
4559         }
4560
4561         if (moving_folder) {
4562                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4563
4564                 /* Get the folder to move */
4565                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4566                 
4567                 /* Check that we're not moving to the same folder */
4568                 if (TNY_IS_FOLDER (moved_folder)) {
4569                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4570                         if (parent == folder_store)
4571                                 ok_sensitive = FALSE;
4572                         g_object_unref (parent);
4573                 } 
4574
4575                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4576                         /* Do not allow to move to an account unless it's the
4577                            local folders account */
4578                         if (!is_local_account)
4579                                 ok_sensitive = FALSE;
4580                 } 
4581
4582                 if (ok_sensitive && (moved_folder == folder_store)) {
4583                         /* Do not allow to move to itself */
4584                         ok_sensitive = FALSE;
4585                 }
4586                 g_object_unref (moved_folder);
4587         } else {
4588                 TnyFolder *src_folder = NULL;
4589
4590                 /* Moving a message */
4591                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4592
4593                         TnyHeader *header = NULL;
4594                         header = modest_msg_view_window_get_header
4595                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4596                         if (!TNY_IS_HEADER(header))
4597                                 g_warning ("%s: could not get source header", __FUNCTION__);
4598                         else
4599                                 src_folder = tny_header_get_folder (header);
4600
4601                         if (header)
4602                                 g_object_unref (header);
4603                 } else {
4604                         src_folder = 
4605                                 TNY_FOLDER (modest_folder_view_get_selected
4606                                             (MODEST_FOLDER_VIEW (folder_view)));
4607                 }
4608
4609                 if (TNY_IS_FOLDER(src_folder)) {
4610                         /* Do not allow to move the msg to the same folder */
4611                         /* Do not allow to move the msg to an account */
4612                         if ((gpointer) src_folder == (gpointer) folder_store ||
4613                             TNY_IS_ACCOUNT (folder_store))
4614                                 ok_sensitive = FALSE;
4615                         g_object_unref (src_folder);
4616                 } else
4617                         g_warning ("%s: could not get source folder", __FUNCTION__);
4618         }
4619
4620  end:
4621         /* Set sensitivity of the OK button */
4622         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4623         /* Set sensitivity of the NEW button */
4624         gtk_widget_set_sensitive (new_button, new_sensitive);
4625 }
4626
4627
4628 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4629
4630 static GtkWidget*
4631 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4632 {
4633         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4634                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4635 }
4636
4637 static GtkWidget*
4638 create_move_to_dialog (GtkWindow *win,
4639                        GtkWidget *folder_view,
4640                        GtkWidget **tree_view)
4641 {
4642         GtkWidget *dialog, *scroll;
4643         GtkWidget *new_button, *ok_button;
4644
4645         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4646                                               GTK_WINDOW (win),
4647                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4648                                               NULL);
4649
4650 #ifndef MODEST_TOOLKIT_GTK
4651         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4652         /* We do this manually so GTK+ does not associate a response ID for
4653          * the button. */
4654         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4655         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4656         gtk_widget_show (new_button);
4657 #ifndef MODEST_TOOLKIT_HILDON2
4658         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4659 #endif
4660 #else
4661         /* We do this manually so GTK+ does not associate a response ID for
4662          * the button. */
4663         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4664         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4665         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4666         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4667         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4668         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4669         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4670 #endif
4671         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON, ok_button);
4672         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON, new_button);
4673
4674         /* Create scrolled window */
4675         scroll = gtk_scrolled_window_new (NULL, NULL);
4676         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4677                                          GTK_POLICY_AUTOMATIC,
4678                                          GTK_POLICY_AUTOMATIC);
4679
4680 #ifdef MODEST_TOOLKIT_GTK
4681         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4682 #endif
4683
4684         /* Create folder view */
4685         *tree_view = modest_platform_create_folder_view (NULL);
4686
4687         /* Track changes in the selection to
4688          * disable the OK button whenever "Move to" is not possible
4689          * disbale NEW button whenever New is not possible */
4690         g_signal_connect (*tree_view,
4691                           "folder_selection_changed",
4692                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4693                           win);
4694
4695         /* Listen to clicks on New button */
4696         g_signal_connect (G_OBJECT (new_button), 
4697                           "clicked", 
4698                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4699                           *tree_view);
4700
4701         /* It could happen that we're trying to move a message from a
4702            window (msg window for example) after the main window was
4703            closed, so we can not just get the model of the folder
4704            view */
4705         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4706                 const gchar *visible_id = NULL;
4707
4708                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4709                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4710                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4711                                                MODEST_FOLDER_VIEW(*tree_view));
4712
4713                 visible_id = 
4714                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4715
4716                 /* Show the same account than the one that is shown in the main window */
4717                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4718                                                                              visible_id);
4719         } else {
4720                 const gchar *active_account_name = NULL;
4721                 ModestAccountMgr *mgr = NULL;
4722                 ModestAccountSettings *settings = NULL;
4723                 ModestServerAccountSettings *store_settings = NULL;
4724
4725                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4726                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4727                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4728                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4729
4730                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4731                 mgr = modest_runtime_get_account_mgr ();
4732                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4733
4734                 if (settings) {
4735                         const gchar *store_account_name;
4736                         store_settings = modest_account_settings_get_store_settings (settings);
4737                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4738
4739                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4740                                                                                      store_account_name);
4741                         g_object_unref (store_settings);
4742                         g_object_unref (settings);
4743                 }
4744         }
4745
4746         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4747          *   get_folder_view_from_move_to_dialog 
4748          * (see above) later (needed for focus handling) 
4749          */
4750         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4751
4752         
4753         /* Hide special folders */
4754         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4755
4756         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4757
4758         /* Add scroll to dialog */
4759         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4760                             scroll, TRUE, TRUE, 0);
4761
4762         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4763 #ifndef MODEST_TOOLKIT_GTK
4764         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4765 #else
4766         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4767 #endif
4768
4769         return dialog;
4770 }
4771
4772
4773
4774 /*
4775  * Shows a confirmation dialog to the user when we're moving messages
4776  * from a remote server to the local storage. Returns the dialog
4777  * response. If it's other kind of movement then it always returns
4778  * GTK_RESPONSE_OK
4779  *
4780  * This one is used by the next functions:
4781  *      modest_ui_actions_on_paste                      - commented out
4782  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4783  */
4784 gint
4785 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4786                                              TnyFolder *dest_folder,
4787                                              gboolean delete,
4788                                              TnyList *headers)
4789 {
4790         gint response = GTK_RESPONSE_OK;
4791         TnyAccount *account = NULL;
4792         TnyFolder *src_folder = NULL;
4793         TnyIterator *iter = NULL;
4794         TnyHeader *header = NULL;
4795
4796         /* return with OK if the destination is a remote folder */
4797         if (modest_tny_folder_is_remote_folder (dest_folder))
4798                 return GTK_RESPONSE_OK;
4799
4800         /* Get source folder */
4801         iter = tny_list_create_iterator (headers);
4802         header = TNY_HEADER (tny_iterator_get_current (iter));
4803         if (header) {
4804                 src_folder = tny_header_get_folder (header);
4805                 g_object_unref (header);
4806         }
4807         g_object_unref (iter);
4808
4809         /* if no src_folder, message may be an attahcment */
4810         if (src_folder == NULL) 
4811                 return GTK_RESPONSE_CANCEL;
4812
4813         /* If the source is a local or MMC folder */
4814         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4815                 g_object_unref (src_folder);
4816                 return GTK_RESPONSE_OK;
4817         }
4818
4819         /* Get the account */
4820         account = tny_folder_get_account (src_folder);
4821
4822         /* now if offline we ask the user */
4823         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4824                 response = GTK_RESPONSE_OK;
4825         else
4826                 response = GTK_RESPONSE_CANCEL;
4827
4828         /* Frees */
4829         g_object_unref (src_folder);
4830         g_object_unref (account);
4831
4832         return response;
4833 }
4834
4835 static void
4836 move_to_helper_destroyer (gpointer user_data)
4837 {
4838         MoveToHelper *helper = (MoveToHelper *) user_data;
4839
4840         /* Close the "Pasting" information banner */
4841         if (helper->banner) {
4842                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4843                 g_object_unref (helper->banner);
4844         }
4845         if (helper->reference != NULL)
4846                 gtk_tree_row_reference_free (helper->reference);
4847         g_free (helper);
4848 }
4849
4850 static void
4851 move_to_cb (ModestMailOperation *mail_op, 
4852             gpointer user_data)
4853 {
4854         MoveToHelper *helper = (MoveToHelper *) user_data;
4855
4856         /* Note that the operation could have failed, in that case do
4857            nothing */
4858         if (modest_mail_operation_get_status (mail_op) == 
4859             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4860
4861                 GObject *object = modest_mail_operation_get_source (mail_op);
4862                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4863                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4864
4865                         if (!modest_msg_view_window_select_next_message (self) &&
4866                             !modest_msg_view_window_select_previous_message (self)) {
4867                                 /* No more messages to view, so close this window */
4868                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4869                         }
4870                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4871                         GtkWidget *header_view;
4872                         GtkTreePath *path;
4873                         GtkTreeSelection *sel;
4874
4875                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4876                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4877                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4878                         path = gtk_tree_row_reference_get_path (helper->reference);
4879                         /* We need to unselect the previous one
4880                            because we could be copying instead of
4881                            moving */
4882                         gtk_tree_selection_unselect_all (sel);
4883                         gtk_tree_selection_select_path (sel, path);
4884                         gtk_tree_path_free (path);
4885                 }
4886                 g_object_unref (object);
4887         }
4888         /* Destroy the helper */
4889         move_to_helper_destroyer (helper);
4890 }
4891
4892 static void
4893 folder_move_to_cb (ModestMailOperation *mail_op, 
4894                    TnyFolder *new_folder,
4895                    gpointer user_data)
4896 {
4897         GtkWidget *folder_view;
4898         GObject *object;
4899
4900         object = modest_mail_operation_get_source (mail_op);
4901         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4902                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4903         g_object_ref (folder_view);
4904         g_object_unref (object);
4905         move_to_cb (mail_op, user_data);
4906         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4907         g_object_unref (folder_view);
4908 }
4909
4910 static void
4911 msgs_move_to_cb (ModestMailOperation *mail_op, 
4912                  gpointer user_data)
4913 {
4914         move_to_cb (mail_op, user_data);
4915 }
4916
4917 void
4918 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4919                                              gpointer user_data)
4920 {
4921         ModestWindow *main_window = NULL;
4922         
4923         /* Disable next automatic folder selection */
4924         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4925                                                          FALSE); /* don't create */
4926         if (main_window) {
4927                 GObject *win = NULL;
4928                 GtkWidget *folder_view = NULL;
4929         
4930                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4931                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4932                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4933                 
4934                 if (user_data && TNY_IS_FOLDER (user_data)) {
4935                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4936                                                           TNY_FOLDER (user_data), FALSE);
4937                 }
4938
4939                 /* Show notification dialog only if the main window exists */
4940                 win = modest_mail_operation_get_source (mail_op);
4941                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4942                                                         _("mail_in_ui_folder_move_target_error"), 
4943                                                         FALSE);
4944                 if (win)
4945                         g_object_unref (win);
4946         }
4947 }
4948
4949 static void
4950 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4951                        TnyHeader *header, 
4952                        gboolean canceled,
4953                        TnyMsg *msg, 
4954                        GError *err,
4955                        gpointer user_data)
4956 {
4957         TnyList *parts;
4958         TnyIterator *iter;
4959         gint pending_purges = 0;
4960         gboolean some_purged = FALSE;
4961         ModestWindow *win = MODEST_WINDOW (user_data);
4962         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4963
4964         /* If there was any error */
4965         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4966                 modest_window_mgr_unregister_header (mgr, header);
4967                 return;
4968         }
4969
4970         /* Once the message has been retrieved for purging, we check if
4971          * it's all ok for purging */
4972
4973         parts = tny_simple_list_new ();
4974         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4975         iter = tny_list_create_iterator (parts);
4976
4977         while (!tny_iterator_is_done (iter)) {
4978                 TnyMimePart *part;
4979                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4980                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4981                         if (tny_mime_part_is_purged (part))
4982                                 some_purged = TRUE;
4983                         else
4984                                 pending_purges++;
4985                 }
4986
4987                 if (part)
4988                         g_object_unref (part);
4989
4990                 tny_iterator_next (iter);
4991         }
4992         g_object_unref (iter);
4993         
4994
4995         if (pending_purges>0) {
4996                 gint response;
4997                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4998
4999                 if (response == GTK_RESPONSE_OK) {
5000                         GtkWidget *info;
5001                         info =
5002                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
5003                         iter = tny_list_create_iterator (parts);
5004                         while (!tny_iterator_is_done (iter)) {
5005                                 TnyMimePart *part;
5006                                 
5007                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5008                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5009                                         tny_mime_part_set_purged (part);
5010
5011                                 if (part)
5012                                         g_object_unref (part);
5013
5014                                 tny_iterator_next (iter);
5015                         }
5016                         g_object_unref (iter);
5017                         
5018                         tny_msg_rewrite_cache (msg);
5019
5020                         gtk_widget_destroy (info);
5021                 }
5022         }
5023
5024         modest_window_mgr_unregister_header (mgr, header);
5025
5026         g_object_unref (parts);
5027 }
5028
5029 static void
5030 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5031                                                      ModestMainWindow *win)
5032 {
5033         GtkWidget *header_view;
5034         TnyList *header_list;
5035         TnyHeader *header;
5036         TnyHeaderFlags flags;
5037         ModestWindow *msg_view_window =  NULL;
5038         gboolean found;
5039
5040         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5041
5042         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5043                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5044
5045         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5046         if (!header_list) {
5047                 g_warning ("%s: no header selected", __FUNCTION__);
5048                 return;
5049         }
5050         
5051         if (tny_list_get_length (header_list) == 1) {
5052                 TnyIterator *iter = tny_list_create_iterator (header_list);
5053                 header = TNY_HEADER (tny_iterator_get_current (iter));
5054                 g_object_unref (iter);
5055         } else
5056                 return;
5057         
5058         if (!header || !TNY_IS_HEADER(header)) {
5059                 g_warning ("%s: header is not valid", __FUNCTION__);
5060                 return;
5061         }
5062         
5063         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5064                                                           header, &msg_view_window);
5065         flags = tny_header_get_flags (header);
5066         if (!(flags & TNY_HEADER_FLAG_CACHED))
5067                 return;
5068         if (found) {
5069                 if (msg_view_window != NULL) 
5070                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5071                 else {
5072                         /* do nothing; uid was registered before, so window is probably on it's way */
5073                         g_warning ("debug: header %p has already been registered", header);
5074                 }
5075         } else {
5076                 ModestMailOperation *mail_op = NULL;
5077                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5078                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5079                                                                          modest_ui_actions_disk_operations_error_handler,
5080                                                                          NULL, NULL);
5081                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5082                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5083                 
5084                 g_object_unref (mail_op);
5085         }
5086         if (header)
5087                 g_object_unref (header);
5088         if (header_list)
5089                 g_object_unref (header_list);
5090 }
5091
5092 /*
5093  * Checks if we need a connection to do the transfer and if the user
5094  * wants to connect to complete it
5095  */
5096 void
5097 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5098                                        TnyFolderStore *src_folder,
5099                                        TnyList *headers,
5100                                        TnyFolder *dst_folder,
5101                                        gboolean delete_originals,
5102                                        gboolean *need_connection,
5103                                        gboolean *do_xfer)
5104 {
5105         TnyAccount *src_account;
5106         gint uncached_msgs = 0;
5107
5108         uncached_msgs = header_list_count_uncached_msgs (headers);
5109
5110         /* We don't need any further check if
5111          *
5112          * 1- the source folder is local OR
5113          * 2- the device is already online
5114          */
5115         if (!modest_tny_folder_store_is_remote (src_folder) ||
5116             tny_device_is_online (modest_runtime_get_device())) {
5117                 *need_connection = FALSE;
5118                 *do_xfer = TRUE;
5119                 return;
5120         }
5121
5122         /* We must ask for a connection when
5123          *
5124          *   - the message(s) is not already cached   OR 
5125          *   - the message(s) is cached but the leave_on_server setting
5126          * is FALSE (because we need to sync the source folder to
5127          * delete the message from the server (for IMAP we could do it
5128          * offline, it'll take place the next time we get a
5129          * connection)
5130          */
5131         src_account = get_account_from_folder_store (src_folder);
5132         if (uncached_msgs > 0) {
5133                 guint num_headers;
5134                 const gchar *msg;
5135
5136                 *need_connection = TRUE;
5137                 num_headers = tny_list_get_length (headers);
5138                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5139
5140                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5141                     GTK_RESPONSE_CANCEL) {
5142                         *do_xfer = FALSE;
5143                 } else {
5144                         *do_xfer = TRUE;
5145                 }
5146         } else {
5147                 /* The transfer is possible and the user wants to */
5148                 *do_xfer = TRUE;
5149
5150                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5151                         const gchar *account_name;
5152                         gboolean leave_on_server;
5153                         
5154                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5155                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5156                                                                                   account_name);
5157                         
5158                         if (leave_on_server == TRUE) {
5159                                 *need_connection = FALSE;
5160                         } else {
5161                                 *need_connection = TRUE;
5162                         }
5163                 } else {
5164                         *need_connection = FALSE;
5165                 }
5166         }
5167
5168         /* Frees */
5169         g_object_unref (src_account);
5170 }
5171
5172 static void
5173 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5174                              gpointer user_data)
5175 {
5176         ModestWindow *main_window = NULL;
5177
5178         /* Disable next automatic folder selection */
5179         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5180                                                          FALSE); /* don't create */
5181         if (main_window) {
5182                 GObject *win = modest_mail_operation_get_source (mail_op);
5183                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5184                                                         _("mail_in_ui_folder_move_target_error"), 
5185                                                         FALSE);
5186                 if (win)
5187                         g_object_unref (win);
5188         }
5189         move_to_helper_destroyer (user_data);
5190 }
5191
5192 typedef struct {
5193         TnyFolderStore *dst_folder;
5194         TnyList *headers;
5195 } XferMsgsHelper;
5196
5197 /**
5198  * Utility function that transfer messages from both the main window
5199  * and the msg view window when using the "Move to" dialog
5200  */
5201 static void
5202 xfer_messages_performer  (gboolean canceled, 
5203                           GError *err,
5204                           GtkWindow *parent_window, 
5205                           TnyAccount *account, 
5206                           gpointer user_data)
5207 {
5208         ModestWindow *win = MODEST_WINDOW (parent_window);
5209         TnyAccount *dst_account = NULL;
5210         gboolean dst_forbids_message_add = FALSE;
5211         XferMsgsHelper *helper;
5212         MoveToHelper *movehelper;
5213         ModestMailOperation *mail_op;
5214
5215         helper = (XferMsgsHelper *) user_data;
5216
5217         if (canceled || err) {
5218                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5219                         /* Show the proper error message */
5220                         modest_ui_actions_on_account_connection_error (parent_window, account);
5221                 }
5222                 goto end;
5223         }
5224
5225         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5226
5227         /* tinymail will return NULL for local folders it seems */
5228         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5229                                                                                   modest_tny_account_get_protocol_type (dst_account),
5230                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5231         g_object_unref (dst_account);
5232
5233         if (dst_forbids_message_add) {
5234                 modest_platform_information_banner (GTK_WIDGET (win),
5235                                                     NULL,
5236                                                     ngettext("mail_in_ui_folder_move_target_error",
5237                                                              "mail_in_ui_folder_move_targets_error",
5238                                                              tny_list_get_length (helper->headers)));
5239                 goto end;
5240         }
5241
5242         movehelper = g_new0 (MoveToHelper, 1);
5243         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5244                                                                _CS("ckct_nw_pasting"));
5245         if (movehelper->banner != NULL)  {
5246                 g_object_ref (movehelper->banner);
5247                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5248         }
5249
5250         if (MODEST_IS_MAIN_WINDOW (win)) {
5251                 GtkWidget *header_view = 
5252                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5253                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5254                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5255         }
5256
5257         /* Perform the mail operation */
5258         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5259                                                                  xfer_messages_error_handler,
5260                                                                  movehelper, NULL);
5261         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5262                                          mail_op);
5263
5264         modest_mail_operation_xfer_msgs (mail_op, 
5265                                          helper->headers,
5266                                          TNY_FOLDER (helper->dst_folder),
5267                                          TRUE,
5268                                          msgs_move_to_cb,
5269                                          movehelper);
5270
5271         g_object_unref (G_OBJECT (mail_op));
5272  end:
5273         g_object_unref (helper->dst_folder);
5274         g_object_unref (helper->headers);
5275         g_slice_free (XferMsgsHelper, helper);
5276 }
5277
5278 typedef struct {
5279         TnyFolder *src_folder;
5280         TnyFolderStore *dst_folder;
5281         gboolean delete_original;
5282         GtkWidget *folder_view;
5283 } MoveFolderInfo;
5284
5285 static void
5286 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5287                 TnyAccount *account, gpointer user_data)
5288 {
5289         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5290         GtkTreeSelection *sel;
5291         ModestMailOperation *mail_op = NULL;
5292         
5293         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5294                 g_object_unref (G_OBJECT (info->src_folder));
5295                 g_object_unref (G_OBJECT (info->dst_folder));
5296                 g_free (info);
5297                 return;
5298         }
5299         
5300         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5301         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5302                         _CS("ckct_nw_pasting"));
5303         if (helper->banner != NULL)  {
5304                 g_object_ref (helper->banner);
5305                 gtk_widget_show (GTK_WIDGET(helper->banner));
5306         }
5307         /* Clean folder on header view before moving it */
5308         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5309         gtk_tree_selection_unselect_all (sel);
5310
5311         /* Let gtk events run. We need that the folder
5312            view frees its reference to the source
5313            folder *before* issuing the mail operation
5314            so we need the signal handler of selection
5315            changed to happen before the mail
5316            operation 
5317         while (gtk_events_pending ())
5318                 gtk_main_iteration ();   */
5319
5320         mail_op =
5321                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5322                                 modest_ui_actions_move_folder_error_handler,
5323                                 info->src_folder, NULL);
5324         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5325                         mail_op);
5326
5327         /* Select *after* the changes */
5328         /* TODO: this function hangs UI after transfer */ 
5329         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5330         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5331
5332         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5333                                           TNY_FOLDER (info->dst_folder), TRUE);
5334         modest_mail_operation_xfer_folder (mail_op,
5335                         TNY_FOLDER (info->src_folder),
5336                         info->dst_folder,
5337                         info->delete_original, 
5338                         folder_move_to_cb, 
5339                         helper);
5340         g_object_unref (G_OBJECT (info->src_folder));
5341
5342         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5343         /* } */
5344         
5345         /* Unref mail operation */
5346         g_object_unref (G_OBJECT (mail_op));
5347         g_object_unref (G_OBJECT (info->dst_folder));
5348         g_free (user_data);
5349 }
5350
5351 static TnyAccount *
5352 get_account_from_folder_store (TnyFolderStore *folder_store) 
5353 {
5354         if (TNY_IS_ACCOUNT (folder_store))
5355                 return g_object_ref (folder_store);
5356         else
5357                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5358 }
5359
5360 /*
5361  * UI handler for the "Move to" action when invoked from the
5362  * ModestMainWindow
5363  */
5364 static void 
5365 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5366                                           GtkWidget *folder_view,
5367                                           TnyFolderStore *dst_folder,
5368                                           ModestMainWindow *win)
5369 {
5370         ModestHeaderView *header_view = NULL;
5371         TnyFolderStore *src_folder = NULL;
5372
5373         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5374
5375         /* Get the source folder */
5376         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5377
5378         /* Get header view */
5379         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5380
5381         /* Get folder or messages to transfer */
5382         if (gtk_widget_is_focus (folder_view)) {
5383                 gboolean do_xfer = TRUE;
5384
5385                 /* Allow only to transfer folders to the local root folder */
5386                 if (TNY_IS_ACCOUNT (dst_folder) && 
5387                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5388                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5389                         do_xfer = FALSE;
5390                 } else if (!TNY_IS_FOLDER (src_folder)) {
5391                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5392                         do_xfer = FALSE;
5393                 }
5394
5395                 if (do_xfer) {                  
5396                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5397                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5398
5399                         info->src_folder = g_object_ref (src_folder);
5400                         info->dst_folder = g_object_ref (dst_folder);
5401                         info->delete_original = TRUE;
5402                         info->folder_view = folder_view;
5403
5404                         connect_info->callback = on_move_folder_cb;
5405                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5406                         connect_info->data = info;
5407
5408                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5409                                                                    TNY_FOLDER_STORE (src_folder), 
5410                                                                    connect_info);
5411                 }
5412         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5413                 TnyList *headers;
5414
5415                 headers = modest_header_view_get_selected_headers(header_view);
5416
5417                 /* Transfer the messages */
5418                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5419                                                             headers, TNY_FOLDER (dst_folder));
5420
5421                 g_object_unref (headers);
5422         }
5423
5424         /* Frees */
5425         g_object_unref (src_folder);
5426 }
5427
5428
5429 void
5430 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5431                                             TnyFolder *src_folder,
5432                                             TnyList *headers,
5433                                             TnyFolder *dst_folder)
5434 {
5435         gboolean need_connection = TRUE;
5436         gboolean do_xfer = TRUE;
5437         XferMsgsHelper *helper;
5438
5439         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5440         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5441         g_return_if_fail (TNY_IS_LIST (headers));
5442         
5443         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5444                                                headers, TNY_FOLDER (dst_folder),
5445                                                TRUE, &need_connection, 
5446                                                &do_xfer);
5447
5448         /* If we don't want to transfer just return */
5449         if (!do_xfer)
5450                 return;
5451
5452         /* Create the helper */
5453         helper = g_slice_new (XferMsgsHelper);
5454         helper->dst_folder = g_object_ref (dst_folder);
5455         helper->headers = g_object_ref (headers);
5456
5457         if (need_connection) {
5458                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5459                 connect_info->callback = xfer_messages_performer;
5460                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5461                 connect_info->data = helper;
5462                 
5463                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5464                                                            TNY_FOLDER_STORE (src_folder), 
5465                                                            connect_info);
5466         } else {
5467                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5468                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5469                                          src_account, helper);
5470                 g_object_unref (src_account);
5471         }
5472 }
5473
5474 /*
5475  * UI handler for the "Move to" action when invoked from the
5476  * ModestMsgViewWindow
5477  */
5478 static void 
5479 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5480                                               TnyFolderStore *dst_folder,
5481                                               ModestMsgViewWindow *win)
5482 {
5483         TnyList *headers = NULL;
5484         TnyHeader *header = NULL;
5485         TnyFolder *src_folder = NULL;
5486
5487         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5488
5489         /* Create header list */
5490         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5491         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5492         headers = tny_simple_list_new ();
5493         tny_list_append (headers, G_OBJECT (header));
5494
5495         /* Transfer the messages */
5496         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5497                                                     TNY_FOLDER (dst_folder));
5498
5499         /* Frees */
5500         g_object_unref (src_folder);
5501         g_object_unref (header);
5502         g_object_unref (headers);
5503 }
5504
5505 void 
5506 modest_ui_actions_on_move_to (GtkAction *action, 
5507                               ModestWindow *win)
5508 {
5509         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5510         gint result = 0;
5511         TnyFolderStore *dst_folder = NULL;
5512         ModestMainWindow *main_window;
5513
5514         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5515                           MODEST_IS_MSG_VIEW_WINDOW (win));
5516
5517         /* Get the main window if exists */
5518         if (MODEST_IS_MAIN_WINDOW (win))
5519                 main_window = MODEST_MAIN_WINDOW (win);
5520         else
5521                 main_window = 
5522                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5523                                                                                FALSE)); /* don't create */
5524
5525         /* Get the folder view widget if exists */
5526         if (main_window)
5527                 folder_view = modest_main_window_get_child_widget (main_window,
5528                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5529         else
5530                 folder_view = NULL;
5531
5532         /* Create and run the dialog */
5533         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5534         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5535         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) win);
5536         result = gtk_dialog_run (GTK_DIALOG(dialog));
5537         g_object_ref (tree_view);
5538         gtk_widget_destroy (dialog);
5539
5540         if (result != GTK_RESPONSE_ACCEPT)
5541                 return;
5542
5543         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5544         /* Do window specific stuff */
5545         if (MODEST_IS_MAIN_WINDOW (win)) {
5546                 modest_ui_actions_on_main_window_move_to (action,
5547                                 folder_view,
5548                                 dst_folder,
5549                                 MODEST_MAIN_WINDOW (win));
5550         } else {
5551                 modest_ui_actions_on_msg_view_window_move_to (action,
5552                                 dst_folder,
5553                                 MODEST_MSG_VIEW_WINDOW (win));
5554         }
5555
5556         if (dst_folder)
5557                 g_object_unref (dst_folder);
5558 }
5559
5560 /*
5561  * Calls #HeadersFunc for each header already selected in the main
5562  * window or the message currently being shown in the msg view window
5563  */
5564 static void
5565 do_headers_action (ModestWindow *win, 
5566                    HeadersFunc func,
5567                    gpointer user_data)
5568 {
5569         TnyList *headers_list = NULL;
5570         TnyIterator *iter = NULL;
5571         TnyHeader *header = NULL;
5572         TnyFolder *folder = NULL;
5573
5574         /* Get headers */
5575         headers_list = get_selected_headers (win);
5576         if (!headers_list)
5577                 return;
5578
5579         /* Get the folder */
5580         iter = tny_list_create_iterator (headers_list);
5581         header = TNY_HEADER (tny_iterator_get_current (iter));
5582         if (header) {
5583                 folder = tny_header_get_folder (header);
5584                 g_object_unref (header);
5585         }
5586
5587         /* Call the function for each header */
5588         while (!tny_iterator_is_done (iter)) {
5589                 header = TNY_HEADER (tny_iterator_get_current (iter));
5590                 func (header, win, user_data);
5591                 g_object_unref (header);
5592                 tny_iterator_next (iter);
5593         }
5594
5595         /* Trick: do a poke status in order to speed up the signaling
5596            of observers */
5597         tny_folder_poke_status (folder);
5598
5599         /* Frees */
5600         g_object_unref (folder);
5601         g_object_unref (iter);
5602         g_object_unref (headers_list);
5603 }
5604
5605 void 
5606 modest_ui_actions_view_attachment (GtkAction *action,
5607                                    ModestWindow *window)
5608 {
5609         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5610                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5611         } else {
5612                 /* not supported window for this action */
5613                 g_return_if_reached ();
5614         }
5615 }
5616
5617 void
5618 modest_ui_actions_save_attachments (GtkAction *action,
5619                                     ModestWindow *window)
5620 {
5621         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5622
5623                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5624                         return;
5625
5626                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5627         } else {
5628                 /* not supported window for this action */
5629                 g_return_if_reached ();
5630         }
5631 }
5632
5633 void
5634 modest_ui_actions_remove_attachments (GtkAction *action,
5635                                       ModestWindow *window)
5636 {
5637         if (MODEST_IS_MAIN_WINDOW (window)) {
5638                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5639         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5640                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5641         } else {
5642                 /* not supported window for this action */
5643                 g_return_if_reached ();
5644         }
5645 }
5646
5647 void 
5648 modest_ui_actions_on_settings (GtkAction *action, 
5649                                ModestWindow *win)
5650 {
5651         GtkWidget *dialog;
5652
5653         dialog = modest_platform_get_global_settings_dialog ();
5654         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5655         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5656         gtk_widget_show_all (dialog);
5657
5658         gtk_dialog_run (GTK_DIALOG (dialog));
5659
5660         gtk_widget_destroy (dialog);
5661 }
5662
5663 void 
5664 modest_ui_actions_on_help (GtkAction *action, 
5665                            GtkWindow *win)
5666 {
5667         const gchar *help_id;
5668
5669         g_return_if_fail (win && GTK_IS_WINDOW(win));
5670         
5671         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5672
5673         if (help_id)
5674                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5675 }
5676
5677 void 
5678 modest_ui_actions_on_csm_help (GtkAction *action, 
5679                                GtkWindow *win)
5680 {
5681         const gchar* help_id = NULL;
5682         GtkWidget *folder_view;
5683         TnyFolderStore *folder_store;
5684
5685         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5686
5687         /* Get selected folder */
5688         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5689                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5690         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5691
5692         /* Switch help_id */
5693         if (folder_store && TNY_IS_FOLDER (folder_store))
5694                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5695
5696         if (folder_store)
5697                 g_object_unref (folder_store);
5698
5699         if (help_id)
5700                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5701         else
5702                 modest_ui_actions_on_help (action, win);
5703 }
5704
5705 static void     
5706 retrieve_contents_cb (ModestMailOperation *mail_op, 
5707                       TnyHeader *header, 
5708                       gboolean canceled,
5709                       TnyMsg *msg,
5710                       GError *err,
5711                       gpointer user_data)
5712 {
5713         /* We only need this callback to show an error in case of
5714            memory low condition */
5715         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5716 }
5717
5718 static void
5719 retrieve_msg_contents_performer (gboolean canceled, 
5720                                  GError *err,
5721                                  GtkWindow *parent_window, 
5722                                  TnyAccount *account, 
5723                                  gpointer user_data)
5724 {
5725         ModestMailOperation *mail_op;
5726         TnyList *headers = TNY_LIST (user_data);
5727
5728         if (err || canceled) {
5729                 check_memory_full_error ((GtkWidget *) parent_window, err);
5730                 goto out;
5731         }
5732
5733         /* Create mail operation */
5734         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5735                                                                  modest_ui_actions_disk_operations_error_handler, 
5736                                                                  NULL, NULL);
5737         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5738         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5739
5740         /* Frees */
5741         g_object_unref (mail_op);
5742  out:
5743         g_object_unref (headers);
5744         g_object_unref (account);
5745 }
5746
5747 void 
5748 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5749                                             ModestWindow *window)
5750 {
5751         TnyList *headers = NULL;
5752         TnyAccount *account = NULL;
5753         TnyIterator *iter = NULL;
5754         TnyHeader *header = NULL;
5755         TnyFolder *folder = NULL;
5756
5757         /* Get headers */
5758         headers = get_selected_headers (window);
5759         if (!headers)
5760                 return;
5761
5762         /* Pick the account */
5763         iter = tny_list_create_iterator (headers);
5764         header = TNY_HEADER (tny_iterator_get_current (iter));
5765         folder = tny_header_get_folder (header);
5766         account = tny_folder_get_account (folder);
5767         g_object_unref (folder);
5768         g_object_unref (header);
5769         g_object_unref (iter);
5770
5771         /* Connect and perform the message retrieval */
5772         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5773                                              g_object_ref (account), 
5774                                              retrieve_msg_contents_performer, 
5775                                              g_object_ref (headers));
5776
5777         /* Frees */
5778         g_object_unref (account);
5779         g_object_unref (headers);
5780 }
5781
5782 void
5783 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5784 {
5785         g_return_if_fail (MODEST_IS_WINDOW (window));
5786
5787         /* Update dimmed */
5788         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5789 }
5790
5791 void
5792 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5793 {
5794         g_return_if_fail (MODEST_IS_WINDOW (window));
5795
5796         /* Update dimmed */
5797         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5798 }
5799
5800 void
5801 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5802                                           ModestWindow *window)
5803 {
5804         g_return_if_fail (MODEST_IS_WINDOW (window));
5805         
5806         /* Update dimmed */
5807         modest_ui_actions_check_menu_dimming_rules (window);
5808 }
5809
5810 void
5811 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5812                                           ModestWindow *window)
5813 {
5814         g_return_if_fail (MODEST_IS_WINDOW (window));
5815
5816         /* Update dimmed */
5817         modest_ui_actions_check_menu_dimming_rules (window);
5818 }
5819
5820 void
5821 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5822                                           ModestWindow *window)
5823 {
5824         g_return_if_fail (MODEST_IS_WINDOW (window));
5825
5826         /* Update dimmed */
5827         modest_ui_actions_check_menu_dimming_rules (window);
5828 }
5829
5830 void
5831 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5832                                             ModestWindow *window)
5833 {
5834         g_return_if_fail (MODEST_IS_WINDOW (window));
5835
5836         /* Update dimmed */
5837         modest_ui_actions_check_menu_dimming_rules (window);
5838 }
5839
5840 void
5841 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5842                                           ModestWindow *window)
5843 {
5844         g_return_if_fail (MODEST_IS_WINDOW (window));
5845
5846         /* Update dimmed */
5847         modest_ui_actions_check_menu_dimming_rules (window);
5848 }
5849
5850 void
5851 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5852                                           ModestWindow *window)
5853 {
5854         g_return_if_fail (MODEST_IS_WINDOW (window));
5855
5856         /* Update dimmed */
5857         modest_ui_actions_check_menu_dimming_rules (window);
5858 }
5859
5860 void
5861 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5862                                                  ModestWindow *window)
5863 {
5864         g_return_if_fail (MODEST_IS_WINDOW (window));
5865
5866         /* Update dimmed */
5867         modest_ui_actions_check_menu_dimming_rules (window);
5868 }
5869
5870 void
5871 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5872                                                      ModestWindow *window)
5873 {
5874         g_return_if_fail (MODEST_IS_WINDOW (window));
5875
5876         /* Update dimmed */
5877         modest_ui_actions_check_menu_dimming_rules (window);
5878 }
5879
5880 void
5881 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5882                                                      ModestWindow *window)
5883 {
5884         g_return_if_fail (MODEST_IS_WINDOW (window));
5885
5886         /* Update dimmed */
5887         modest_ui_actions_check_menu_dimming_rules (window);
5888 }
5889
5890 void
5891 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5892 {
5893         g_return_if_fail (MODEST_IS_WINDOW (window));
5894
5895         /* we check for low-mem; in that case, show a warning, and don't allow
5896          * searching
5897          */
5898         if (modest_platform_check_memory_low (window, TRUE))
5899                 return;
5900         
5901         modest_platform_show_search_messages (GTK_WINDOW (window));
5902 }
5903
5904 void     
5905 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5906 {
5907         g_return_if_fail (MODEST_IS_WINDOW (win));
5908
5909
5910         /* we check for low-mem; in that case, show a warning, and don't allow
5911          * for the addressbook
5912          */
5913         if (modest_platform_check_memory_low (win, TRUE))
5914                 return;
5915
5916
5917         modest_platform_show_addressbook (GTK_WINDOW (win));
5918 }
5919
5920
5921 void
5922 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5923                                           ModestWindow *window)
5924 {
5925         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5926
5927         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5928 }
5929
5930 static void 
5931 on_send_receive_finished (ModestMailOperation  *mail_op, 
5932                            gpointer user_data)
5933 {
5934         GtkWidget *header_view, *folder_view;
5935         TnyFolderStore *folder_store;
5936         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5937
5938         /* Set send/receive operation finished */       
5939         modest_main_window_notify_send_receive_completed (main_win);
5940
5941         /* Don't refresh the current folder if there were any errors */
5942         if (modest_mail_operation_get_status (mail_op) !=
5943             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5944                 return;
5945         
5946         /* Refresh the current folder if we're viewing a window. We do
5947            this because the user won't be able to see the new mails in
5948            the selected folder after a Send&Receive because it only
5949            performs a poke_status, i.e, only the number of read/unread
5950            messages is updated, but the new headers are not
5951            downloaded */
5952         folder_view = modest_main_window_get_child_widget (main_win, 
5953                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5954         if (!folder_view)
5955                 return;
5956
5957         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5958         
5959         /* Do not need to refresh INBOX again because the
5960            update_account does it always automatically */
5961         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5962             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5963                 ModestMailOperation *refresh_op;
5964
5965                 header_view = modest_main_window_get_child_widget (main_win,
5966                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5967                 
5968                 /* We do not need to set the contents style
5969                    because it hasn't changed. We also do not
5970                    need to save the widget status. Just force
5971                    a refresh */
5972                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5973                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5974                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5975                                                       folder_refreshed_cb, main_win);
5976                 g_object_unref (refresh_op);
5977         }
5978         
5979         if (folder_store)
5980                 g_object_unref (folder_store);
5981 }
5982
5983
5984 void 
5985 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5986                                                 TnyHeader *header, 
5987                                                 TnyMsg *msg, 
5988                                                 GError *err, 
5989                                                 gpointer user_data)
5990 {
5991         const gchar* server_name = NULL;
5992         TnyTransportAccount *server_account;
5993         gchar *message = NULL;
5994
5995         /* Don't show anything if the user cancelled something or the
5996          * send receive request is not interactive. Authentication
5997          * errors are managed by the account store so no need to show
5998          * a dialog here again */
5999         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6000             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6001             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6002                 return;
6003
6004
6005         /* Get the server name: */
6006         server_account = 
6007                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
6008         if (server_account)
6009                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
6010         else
6011                 g_return_if_reached ();
6012
6013         /* Show the appropriate message text for the GError: */
6014         switch (err->code) {
6015         case TNY_SERVICE_ERROR_CONNECT:
6016                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6017                 break;
6018         case TNY_SERVICE_ERROR_SEND:
6019                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6020                 break;
6021         case TNY_SERVICE_ERROR_UNAVAILABLE:
6022                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6023                 break;
6024         default:
6025                 g_warning ("%s: unexpected ERROR %d",
6026                            __FUNCTION__, err->code);
6027                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6028                 break;  
6029         }
6030
6031         modest_platform_run_information_dialog (NULL, message, FALSE);
6032         g_free (message);
6033         g_object_unref (server_account);
6034 }
6035
6036 void
6037 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6038                                                 gchar *msg_id, 
6039                                                 guint status,
6040                                                 gpointer user_data)
6041 {
6042         ModestMainWindow *main_window = NULL;
6043         ModestWindowMgr *mgr = NULL;
6044         GtkWidget *folder_view = NULL, *header_view = NULL;
6045         TnyFolderStore *selected_folder = NULL;
6046         TnyFolderType folder_type;
6047
6048         mgr = modest_runtime_get_window_mgr ();
6049         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6050                                                                              FALSE));/* don't create */
6051         if (!main_window)
6052                 return;
6053
6054         /* Check if selected folder is OUTBOX */
6055         folder_view = modest_main_window_get_child_widget (main_window,
6056                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6057         header_view = modest_main_window_get_child_widget (main_window,
6058                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6059
6060         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6061         if (!TNY_IS_FOLDER (selected_folder)) 
6062                 goto frees;
6063
6064         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6065 #if GTK_CHECK_VERSION(2, 8, 0) 
6066         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6067         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6068                 GtkTreeViewColumn *tree_column;
6069
6070                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6071                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6072                 if (tree_column)
6073                         gtk_tree_view_column_queue_resize (tree_column);
6074         }
6075 #else
6076         gtk_widget_queue_draw (header_view);
6077 #endif          
6078
6079         /* Rerun dimming rules, because the message could become deletable for example */
6080         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6081                                                  MODEST_DIMMING_RULES_TOOLBAR);
6082         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6083                                                  MODEST_DIMMING_RULES_MENU);
6084         
6085         /* Free */
6086  frees:
6087         if (selected_folder != NULL)
6088                 g_object_unref (selected_folder);
6089 }
6090
6091 void 
6092 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6093                                                TnyAccount *account)
6094 {
6095         ModestProtocolType protocol_type;
6096         ModestProtocol *protocol;
6097         gchar *error_note = NULL;
6098         
6099         protocol_type = modest_tny_account_get_protocol_type (account);
6100         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6101                                                                   protocol_type);
6102
6103         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6104         if (error_note == NULL) {
6105                 g_warning ("%s: This should not be reached", __FUNCTION__);
6106         } else {
6107                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6108                 g_free (error_note);
6109         }
6110 }
6111
6112 gchar *
6113 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6114 {
6115         gchar *msg = NULL;
6116         gchar *subject;
6117         TnyFolderStore *folder = NULL;
6118         TnyAccount *account = NULL;
6119         ModestProtocolType proto;
6120         ModestProtocol *protocol;
6121         TnyHeader *header = NULL;
6122
6123         if (MODEST_IS_MAIN_WINDOW (win)) {
6124                 GtkWidget *header_view;
6125                 TnyList* headers = NULL;
6126                 TnyIterator *iter;
6127                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6128                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6129                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6130                 if (!headers || tny_list_get_length (headers) == 0) {
6131                         if (headers)
6132                                 g_object_unref (headers);
6133                         return NULL;
6134                 }
6135                 iter = tny_list_create_iterator (headers);
6136                 header = TNY_HEADER (tny_iterator_get_current (iter));
6137                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6138                 g_object_unref (iter);
6139                 g_object_unref (headers);
6140         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6141                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6142                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6143         }
6144
6145         /* Get the account type */
6146         account = tny_folder_get_account (TNY_FOLDER (folder));
6147         proto = modest_tny_account_get_protocol_type (account);
6148         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6149                                                                   proto);
6150
6151         subject = tny_header_dup_subject (header);
6152         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6153         g_free (subject);
6154         if (msg == NULL) {
6155                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6156         }
6157
6158         /* Frees */
6159         g_object_unref (account);
6160         g_object_unref (folder);
6161         g_object_unref (header);
6162
6163         return msg;
6164 }