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