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