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