* Fixes NB#92083, initialize a variable
[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                         gchar *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 = NULL;
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                                         g_free (*username);
3736                                         /* Show error */
3737                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3738                                                                             _("mcen_ib_username_pw_incorrect"));
3739                                         completed = FALSE;
3740                                 }
3741                         }
3742                         
3743                         if (password) {
3744                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3745                         
3746                                 /* We do not save the password in the configuration, 
3747                                  * because this function is only called for passwords that should 
3748                                  * not be remembered:
3749                                  modest_server_account_set_password (
3750                                  modest_runtime_get_account_mgr(), server_account_name, 
3751                                  *password);
3752                                  */
3753                         }                       
3754                         if (cancel)
3755                                 *cancel   = FALSE;                      
3756                 } else {
3757                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3758                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3759                         completed = TRUE;
3760                         if (username)
3761                                 *username = NULL;                       
3762                         if (password)
3763                                 *password = NULL;                       
3764                         if (cancel)
3765                                 *cancel   = TRUE;
3766                 }
3767         }
3768
3769 /* This is not in the Maemo UI spec:
3770         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3771                 *remember = TRUE;
3772         else
3773                 *remember = FALSE;
3774 */
3775
3776         g_free (initial_username);
3777         gtk_widget_destroy (dialog);
3778         g_slice_free (PasswordDialogFields, fields);
3779         
3780         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3781 }
3782
3783 void
3784 modest_ui_actions_on_cut (GtkAction *action,
3785                           ModestWindow *window)
3786 {
3787         GtkWidget *focused_widget;
3788         GtkClipboard *clipboard;
3789
3790         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3791         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3792         if (GTK_IS_EDITABLE (focused_widget)) {
3793                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3794                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3795                 gtk_clipboard_store (clipboard);
3796         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3797                 GtkTextBuffer *buffer;
3798
3799                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3800                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3801                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3802                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3803                         gtk_clipboard_store (clipboard);
3804                 }
3805         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3806                 TnyList *header_list = modest_header_view_get_selected_headers (
3807                                 MODEST_HEADER_VIEW (focused_widget));
3808                 gboolean continue_download = FALSE;
3809                 gint num_of_unc_msgs;
3810
3811                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3812
3813                 if (num_of_unc_msgs) {
3814                         TnyAccount *account = get_account_from_header_list (header_list);
3815                         if (account) {
3816                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3817                                 g_object_unref (account);
3818                         }
3819                 }
3820
3821                 if (num_of_unc_msgs == 0 || continue_download) {
3822 /*                      modest_platform_information_banner (
3823                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3824                         modest_header_view_cut_selection (
3825                                         MODEST_HEADER_VIEW (focused_widget));
3826                 }
3827
3828                 g_object_unref (header_list);
3829         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3830                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3831         }
3832 }
3833
3834 void
3835 modest_ui_actions_on_copy (GtkAction *action,
3836                            ModestWindow *window)
3837 {
3838         GtkClipboard *clipboard;
3839         GtkWidget *focused_widget;
3840         gboolean copied = TRUE;
3841
3842         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3843         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3844
3845         if (GTK_IS_LABEL (focused_widget)) {
3846                 gchar *selection;
3847                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3848                 gtk_clipboard_set_text (clipboard, selection, -1);
3849                 g_free (selection);
3850                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3851                 gtk_clipboard_store (clipboard);
3852         } else if (GTK_IS_EDITABLE (focused_widget)) {
3853                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3854                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3855                 gtk_clipboard_store (clipboard);
3856         } else if (GTK_IS_HTML (focused_widget)) {
3857                 const gchar *sel;
3858                 int len = -1;
3859                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3860                 if ((sel == NULL) || (sel[0] == '\0')) {
3861                         copied = FALSE;
3862                 } else {
3863                         gtk_html_copy (GTK_HTML (focused_widget));
3864                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3865                         gtk_clipboard_store (clipboard);
3866                 }
3867         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3868                 GtkTextBuffer *buffer;
3869                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3870                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3871                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3872                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3873                         gtk_clipboard_store (clipboard);
3874                 }
3875         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3876                 TnyList *header_list = modest_header_view_get_selected_headers (
3877                                 MODEST_HEADER_VIEW (focused_widget));
3878                 gboolean continue_download = FALSE;
3879                 gint num_of_unc_msgs;
3880
3881                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3882
3883                 if (num_of_unc_msgs) {
3884                         TnyAccount *account = get_account_from_header_list (header_list);
3885                         if (account) {
3886                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3887                                 g_object_unref (account);
3888                         }
3889                 }
3890
3891                 if (num_of_unc_msgs == 0 || continue_download) {
3892                         modest_platform_information_banner (
3893                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3894                         modest_header_view_copy_selection (
3895                                         MODEST_HEADER_VIEW (focused_widget));
3896                 } else
3897                         copied = FALSE;
3898
3899                 g_object_unref (header_list);
3900
3901         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3902                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3903         }
3904
3905         /* Show information banner if there was a copy to clipboard */
3906         if(copied)
3907                 modest_platform_information_banner (
3908                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3909 }
3910
3911 void
3912 modest_ui_actions_on_undo (GtkAction *action,
3913                            ModestWindow *window)
3914 {
3915         ModestEmailClipboard *clipboard = NULL;
3916
3917         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3918                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3919         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3920                 /* Clear clipboard source */
3921                 clipboard = modest_runtime_get_email_clipboard ();
3922                 modest_email_clipboard_clear (clipboard);               
3923         }
3924         else {
3925                 g_return_if_reached ();
3926         }
3927 }
3928
3929 void
3930 modest_ui_actions_on_redo (GtkAction *action,
3931                            ModestWindow *window)
3932 {
3933         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3934                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3935         }
3936         else {
3937                 g_return_if_reached ();
3938         }
3939 }
3940
3941
3942 static void
3943 destroy_information_note (ModestMailOperation *mail_op, 
3944                           gpointer user_data)
3945 {
3946         /* destroy information note */
3947         gtk_widget_destroy (GTK_WIDGET(user_data));
3948 }
3949
3950 static void
3951 destroy_folder_information_note (ModestMailOperation *mail_op, 
3952                                  TnyFolder *new_folder,
3953                                  gpointer user_data)
3954 {
3955         /* destroy information note */
3956         gtk_widget_destroy (GTK_WIDGET(user_data));
3957 }
3958
3959
3960 static void
3961 paste_as_attachment_free (gpointer data)
3962 {
3963         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3964
3965         if (helper->banner) {
3966                 gtk_widget_destroy (helper->banner);
3967                 g_object_unref (helper->banner);
3968         }
3969         g_free (helper);
3970 }
3971
3972 static void
3973 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3974                             TnyHeader *header,
3975                             TnyMsg *msg,
3976                             gpointer userdata)
3977 {
3978         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3979         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3980
3981         if (msg == NULL)
3982                 return;
3983
3984         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3985         
3986 }
3987
3988 void
3989 modest_ui_actions_on_paste (GtkAction *action,
3990                             ModestWindow *window)
3991 {
3992         GtkWidget *focused_widget = NULL;
3993         GtkWidget *inf_note = NULL;
3994         ModestMailOperation *mail_op = NULL;
3995
3996         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3997         if (GTK_IS_EDITABLE (focused_widget)) {
3998                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3999         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4000                 ModestEmailClipboard *e_clipboard = NULL;
4001                 e_clipboard = modest_runtime_get_email_clipboard ();
4002                 if (modest_email_clipboard_cleared (e_clipboard)) {
4003                         GtkTextBuffer *buffer;
4004                         GtkClipboard *clipboard;
4005
4006                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4007                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4008                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4009                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4010                         ModestMailOperation *mail_op;
4011                         TnyFolder *src_folder = NULL;
4012                         TnyList *data = NULL;
4013                         gboolean delete;
4014                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4015                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4016                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4017                                                                            _CS("ckct_nw_pasting"));
4018                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4019                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4020                         if (helper->banner != NULL) {
4021                                 g_object_ref (G_OBJECT (helper->banner));
4022                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4023                         }
4024
4025                         if (data != NULL) {
4026                                 modest_mail_operation_get_msgs_full (mail_op, 
4027                                                                      data,
4028                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4029                                                                      helper,
4030                                                                      paste_as_attachment_free);
4031                         }
4032                         /* Free */
4033                         if (data) 
4034                                 g_object_unref (data);
4035                         if (src_folder) 
4036                                 g_object_unref (src_folder);
4037
4038                 }
4039         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4040                 ModestEmailClipboard *clipboard = NULL;
4041                 TnyFolder *src_folder = NULL;
4042                 TnyFolderStore *folder_store = NULL;
4043                 TnyList *data = NULL;           
4044                 gboolean delete = FALSE;
4045                 
4046                 /* Check clipboard source */
4047                 clipboard = modest_runtime_get_email_clipboard ();
4048                 if (modest_email_clipboard_cleared (clipboard)) 
4049                         return;
4050                 
4051                 /* Get elements to paste */
4052                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4053
4054                 /* Create a new mail operation */
4055                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4056                 
4057                 /* Get destination folder */
4058                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4059
4060                 /* transfer messages  */
4061                 if (data != NULL) {
4062                         gint response = 0;
4063
4064                         /* Ask for user confirmation */
4065                         response = 
4066                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4067                                                                              TNY_FOLDER (folder_store), 
4068                                                                              delete,
4069                                                                              data);
4070                         
4071                         if (response == GTK_RESPONSE_OK) {
4072                                 /* Launch notification */
4073                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4074                                                                              _CS("ckct_nw_pasting"));
4075                                 if (inf_note != NULL)  {
4076                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4077                                         gtk_widget_show (GTK_WIDGET(inf_note));
4078                                 }
4079
4080                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4081                                 modest_mail_operation_xfer_msgs (mail_op, 
4082                                                                  data,
4083                                                                  TNY_FOLDER (folder_store),
4084                                                                  delete,
4085                                                                  destroy_information_note,
4086                                                                  inf_note);                             
4087                         } else {
4088                                 g_object_unref (mail_op);
4089                         }
4090                         
4091                 } else if (src_folder != NULL) {                        
4092                         /* Launch notification */
4093                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4094                                                                      _CS("ckct_nw_pasting"));
4095                         if (inf_note != NULL)  {
4096                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4097                                 gtk_widget_show (GTK_WIDGET(inf_note));
4098                         }
4099                         
4100                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4101                         modest_mail_operation_xfer_folder (mail_op, 
4102                                                            src_folder,
4103                                                            folder_store,
4104                                                            delete,
4105                                                            destroy_folder_information_note,
4106                                                            inf_note);
4107                 }
4108
4109                 /* Free */
4110                 if (data != NULL) 
4111                         g_object_unref (data);
4112                 if (src_folder != NULL) 
4113                         g_object_unref (src_folder);
4114                 if (folder_store != NULL) 
4115                         g_object_unref (folder_store);
4116         }
4117 }
4118
4119
4120 void
4121 modest_ui_actions_on_select_all (GtkAction *action,
4122                                  ModestWindow *window)
4123 {
4124         GtkWidget *focused_widget;
4125
4126         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4127         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4128                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4129         } else if (GTK_IS_LABEL (focused_widget)) {
4130                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4131         } else if (GTK_IS_EDITABLE (focused_widget)) {
4132                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4133         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4134                 GtkTextBuffer *buffer;
4135                 GtkTextIter start, end;
4136
4137                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4138                 gtk_text_buffer_get_start_iter (buffer, &start);
4139                 gtk_text_buffer_get_end_iter (buffer, &end);
4140                 gtk_text_buffer_select_range (buffer, &start, &end);
4141         } else if (GTK_IS_HTML (focused_widget)) {
4142                 gtk_html_select_all (GTK_HTML (focused_widget));
4143         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4144                 GtkWidget *header_view = focused_widget;
4145                 GtkTreeSelection *selection = NULL;
4146                 
4147                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4148                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4149                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4150                 }
4151                                 
4152                 /* Disable window dimming management */
4153                 modest_window_disable_dimming (MODEST_WINDOW(window));
4154                 
4155                 /* Select all messages */
4156                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4157                 gtk_tree_selection_select_all (selection);
4158
4159                 /* Set focuse on header view */
4160                 gtk_widget_grab_focus (header_view);
4161
4162                 /* Enable window dimming management */
4163                 modest_window_enable_dimming (MODEST_WINDOW(window));
4164                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4165                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4166         }
4167
4168 }
4169
4170 void
4171 modest_ui_actions_on_mark_as_read (GtkAction *action,
4172                                    ModestWindow *window)
4173 {       
4174         g_return_if_fail (MODEST_IS_WINDOW(window));
4175                 
4176         /* Mark each header as read */
4177         do_headers_action (window, headers_action_mark_as_read, NULL);
4178 }
4179
4180 void
4181 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4182                                      ModestWindow *window)
4183 {       
4184         g_return_if_fail (MODEST_IS_WINDOW(window));
4185                 
4186         /* Mark each header as read */
4187         do_headers_action (window, headers_action_mark_as_unread, NULL);
4188 }
4189
4190 void
4191 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4192                                   GtkRadioAction *selected,
4193                                   ModestWindow *window)
4194 {
4195         gint value;
4196
4197         value = gtk_radio_action_get_current_value (selected);
4198         if (MODEST_IS_WINDOW (window)) {
4199                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4200         }
4201 }
4202
4203 void
4204 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4205                                                GtkRadioAction *selected,
4206                                                ModestWindow *window)
4207 {
4208         TnyHeaderFlags flags;
4209         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4210
4211         flags = gtk_radio_action_get_current_value (selected);
4212         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4213 }
4214
4215 void
4216 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4217                                                   GtkRadioAction *selected,
4218                                                   ModestWindow *window)
4219 {
4220         gint file_format;
4221
4222         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4223
4224         file_format = gtk_radio_action_get_current_value (selected);
4225         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4226 }
4227
4228
4229 void
4230 modest_ui_actions_on_zoom_plus (GtkAction *action,
4231                                 ModestWindow *window)
4232 {
4233         g_return_if_fail (MODEST_IS_WINDOW (window));
4234
4235         modest_window_zoom_plus (MODEST_WINDOW (window));
4236 }
4237
4238 void     
4239 modest_ui_actions_on_zoom_minus (GtkAction *action,
4240                                  ModestWindow *window)
4241 {
4242         g_return_if_fail (MODEST_IS_WINDOW (window));
4243
4244         modest_window_zoom_minus (MODEST_WINDOW (window));
4245 }
4246
4247 void     
4248 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4249                                            ModestWindow *window)
4250 {
4251         ModestWindowMgr *mgr;
4252         gboolean fullscreen, active;
4253         g_return_if_fail (MODEST_IS_WINDOW (window));
4254
4255         mgr = modest_runtime_get_window_mgr ();
4256
4257         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4258         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4259
4260         if (active != fullscreen) {
4261                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4262 #ifndef MODEST_TOOLKIT_HILDON2
4263                 gtk_window_present (GTK_WINDOW (window));
4264 #endif
4265         }
4266 }
4267
4268 void
4269 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4270                                         ModestWindow *window)
4271 {
4272         ModestWindowMgr *mgr;
4273         gboolean fullscreen;
4274
4275         g_return_if_fail (MODEST_IS_WINDOW (window));
4276
4277         mgr = modest_runtime_get_window_mgr ();
4278         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4279         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4280
4281 #ifndef MODEST_TOOLKIT_HILDON2
4282         gtk_window_present (GTK_WINDOW (window));
4283 #endif
4284 }
4285
4286 /* 
4287  * Used by modest_ui_actions_on_details to call do_headers_action 
4288  */
4289 static void
4290 headers_action_show_details (TnyHeader *header, 
4291                              ModestWindow *window,
4292                              gpointer user_data)
4293
4294 {
4295         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header);
4296 }
4297
4298 /*
4299  * Show the header details in a ModestDetailsDialog widget
4300  */
4301 void     
4302 modest_ui_actions_on_details (GtkAction *action, 
4303                               ModestWindow *win)
4304 {
4305         TnyList * headers_list;
4306         TnyIterator *iter;
4307         TnyHeader *header;              
4308
4309         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4310                 TnyMsg *msg;
4311
4312                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4313                 if (!msg)
4314                         return;
4315                 g_object_unref (msg);           
4316
4317                 headers_list = get_selected_headers (win);
4318                 if (!headers_list)
4319                         return;
4320
4321                 iter = tny_list_create_iterator (headers_list);
4322
4323                 header = TNY_HEADER (tny_iterator_get_current (iter));
4324                 if (header) {
4325                         headers_action_show_details (header, win, NULL);
4326                         g_object_unref (header);
4327                 }
4328
4329                 g_object_unref (iter);
4330                 g_object_unref (headers_list);
4331
4332         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4333                 GtkWidget *folder_view, *header_view;
4334
4335                 /* Check which widget has the focus */
4336                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4337                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4338                 if (gtk_widget_is_focus (folder_view)) {
4339                         TnyFolderStore *folder_store
4340                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4341                         if (!folder_store) {
4342                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4343                                 return; 
4344                         }
4345                         /* Show only when it's a folder */
4346                         /* This function should not be called for account items, 
4347                          * because we dim the menu item for them. */
4348                         if (TNY_IS_FOLDER (folder_store)) {
4349                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win), 
4350                                                                            TNY_FOLDER (folder_store));
4351                         }
4352
4353                         g_object_unref (folder_store);
4354
4355                 } else {
4356                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4357                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4358                         /* Show details of each header */
4359                         do_headers_action (win, headers_action_show_details, header_view);
4360                 }
4361         }
4362 }
4363
4364 void     
4365 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4366                                      ModestMsgEditWindow *window)
4367 {
4368         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4369
4370         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4371 }
4372
4373 void     
4374 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4375                                       ModestMsgEditWindow *window)
4376 {
4377         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4378
4379         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4380 }
4381
4382 void
4383 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4384                                        ModestMainWindow *main_window)
4385 {
4386         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4387
4388         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4389                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4390         else
4391                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4392 }
4393
4394 void 
4395 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4396                                      ModestWindow *window)
4397 {
4398         gboolean active, fullscreen = FALSE;
4399         ModestWindowMgr *mgr;
4400
4401         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4402
4403         /* Check if we want to toggle the toolbar view in fullscreen
4404            or normal mode */
4405         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4406                      "ViewShowToolbarFullScreen")) {
4407                 fullscreen = TRUE;
4408         }
4409
4410         /* Toggle toolbar */
4411         mgr = modest_runtime_get_window_mgr ();
4412         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4413 }
4414
4415 void     
4416 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4417                                            ModestMsgEditWindow *window)
4418 {
4419         modest_msg_edit_window_select_font (window);
4420 }
4421
4422
4423 void
4424 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4425                                                   const gchar *display_name,
4426                                                   GtkWindow *window)
4427 {
4428         /* don't update the display name if it was already set;
4429          * updating the display name apparently is expensive */
4430         const gchar* old_name = gtk_window_get_title (window);
4431
4432         if (display_name == NULL)
4433                 display_name = " ";
4434
4435         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4436                 return; /* don't do anything */
4437
4438         /* This is usually used to change the title of the main window, which
4439          * is the one that holds the folder view. Note that this change can
4440          * happen even when the widget doesn't have the focus. */
4441         gtk_window_set_title (window, display_name);
4442
4443 }
4444
4445 void
4446 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4447 {
4448         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4449         modest_msg_edit_window_select_contacts (window);
4450 }
4451
4452 void
4453 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4454 {
4455         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4456         modest_msg_edit_window_check_names (window, FALSE);
4457 }
4458
4459 static void
4460 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4461 {
4462         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4463                                          GTK_WIDGET (user_data));
4464 }
4465
4466 /*
4467  * This function is used to track changes in the selection of the
4468  * folder view that is inside the "move to" dialog to enable/disable
4469  * the OK button because we do not want the user to select a disallowed
4470  * destination for a folder.
4471  * The user also not desired to be able to use NEW button on items where
4472  * folder creation is not possibel.
4473  */
4474 static void
4475 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4476                                             TnyFolderStore *folder_store,
4477                                             gboolean selected,
4478                                             gpointer user_data)
4479 {
4480         GtkWidget *dialog = NULL;
4481         GtkWidget *ok_button = NULL, *new_button = NULL;
4482         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4483         gboolean moving_folder = FALSE;
4484         gboolean is_local_account = TRUE;
4485         GtkWidget *folder_view = NULL;
4486         ModestTnyFolderRules rules;
4487
4488         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4489         
4490         if (!selected)
4491                 return;
4492         
4493         /* Get the OK button */
4494         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4495         if (!dialog)
4496                 return;
4497
4498         ok_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON);
4499         new_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON);
4500
4501         /* check if folder_store is an remote account */
4502         if (TNY_IS_ACCOUNT (folder_store)) {
4503                 TnyAccount *local_account = NULL;
4504                 TnyAccount *mmc_account = NULL;
4505                 ModestTnyAccountStore *account_store = NULL;
4506
4507                 account_store = modest_runtime_get_account_store ();
4508                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4509                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4510
4511                 if ((gpointer) local_account != (gpointer) folder_store &&
4512                     (gpointer) mmc_account != (gpointer) folder_store) {
4513                         ModestProtocolType proto;
4514                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4515                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4516                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4517                         }
4518                         is_local_account = FALSE;
4519                         /* New button should be dimmed on remote
4520                            POP account root */
4521                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4522                                                                                          proto,
4523                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4524                 }
4525                 g_object_unref (local_account);
4526
4527                 /* It could not exist */
4528                 if (mmc_account)
4529                         g_object_unref (mmc_account);
4530         }
4531
4532         /* Check the target folder rules */
4533         if (TNY_IS_FOLDER (folder_store)) {
4534                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4535                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4536                         ok_sensitive = FALSE;
4537                         new_sensitive = FALSE;
4538                         goto end;
4539                 }
4540         }
4541
4542         /* Check if we're moving a folder */
4543         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4544                 /* Get the widgets */
4545                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4546                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4547                 if (gtk_widget_is_focus (folder_view))
4548                         moving_folder = TRUE;
4549         }
4550
4551         if (moving_folder) {
4552                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4553
4554                 /* Get the folder to move */
4555                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4556                 
4557                 /* Check that we're not moving to the same folder */
4558                 if (TNY_IS_FOLDER (moved_folder)) {
4559                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4560                         if (parent == folder_store)
4561                                 ok_sensitive = FALSE;
4562                         g_object_unref (parent);
4563                 } 
4564
4565                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4566                         /* Do not allow to move to an account unless it's the
4567                            local folders account */
4568                         if (!is_local_account)
4569                                 ok_sensitive = FALSE;
4570                 } 
4571
4572                 if (ok_sensitive && (moved_folder == folder_store)) {
4573                         /* Do not allow to move to itself */
4574                         ok_sensitive = FALSE;
4575                 }
4576                 g_object_unref (moved_folder);
4577         } else {
4578                 TnyFolder *src_folder = NULL;
4579
4580                 /* Moving a message */
4581                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4582
4583                         TnyHeader *header = NULL;
4584                         header = modest_msg_view_window_get_header
4585                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4586                         if (!TNY_IS_HEADER(header))
4587                                 g_warning ("%s: could not get source header", __FUNCTION__);
4588                         else
4589                                 src_folder = tny_header_get_folder (header);
4590
4591                         if (header)
4592                                 g_object_unref (header);
4593                 } else {
4594                         src_folder = 
4595                                 TNY_FOLDER (modest_folder_view_get_selected
4596                                             (MODEST_FOLDER_VIEW (folder_view)));
4597                 }
4598
4599                 if (TNY_IS_FOLDER(src_folder)) {
4600                         /* Do not allow to move the msg to the same folder */
4601                         /* Do not allow to move the msg to an account */
4602                         if ((gpointer) src_folder == (gpointer) folder_store ||
4603                             TNY_IS_ACCOUNT (folder_store))
4604                                 ok_sensitive = FALSE;
4605                         g_object_unref (src_folder);
4606                 } else
4607                         g_warning ("%s: could not get source folder", __FUNCTION__);
4608         }
4609
4610  end:
4611         /* Set sensitivity of the OK button */
4612         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4613         /* Set sensitivity of the NEW button */
4614         gtk_widget_set_sensitive (new_button, new_sensitive);
4615 }
4616
4617
4618 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4619
4620 static GtkWidget*
4621 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4622 {
4623         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4624                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4625 }
4626
4627 static GtkWidget*
4628 create_move_to_dialog (GtkWindow *win,
4629                        GtkWidget *folder_view,
4630                        GtkWidget **tree_view)
4631 {
4632         GtkWidget *dialog;
4633 #ifdef MODEST_TOOLKIT_HILDON2
4634         GtkWidget *pannable;
4635 #else
4636         GtkWidget *scroll;
4637 #endif
4638         GtkWidget *new_button, *ok_button;
4639
4640         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4641                                               GTK_WINDOW (win),
4642                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4643                                               NULL);
4644
4645 #ifndef MODEST_TOOLKIT_GTK
4646         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4647         /* We do this manually so GTK+ does not associate a response ID for
4648          * the button. */
4649         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4650         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4651         gtk_widget_show (new_button);
4652 #ifndef MODEST_TOOLKIT_HILDON2
4653         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4654 #endif
4655 #else
4656         /* We do this manually so GTK+ does not associate a response ID for
4657          * the button. */
4658         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4659         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4660         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4661         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4662         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4663         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4664         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4665 #endif
4666         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON, ok_button);
4667         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON, new_button);
4668
4669         /* Create scrolled window */
4670 #ifdef MODEST_TOOLKIT_HILDON2
4671         pannable = hildon_pannable_area_new ();
4672 #else
4673         scroll = gtk_scrolled_window_new (NULL, NULL);
4674         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4675                                          GTK_POLICY_AUTOMATIC,
4676                                          GTK_POLICY_AUTOMATIC);
4677 #endif
4678
4679 #ifdef MODEST_TOOLKIT_GTK
4680         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4681 #endif
4682
4683         /* Create folder view */
4684         *tree_view = modest_platform_create_folder_view (NULL);
4685
4686         /* Track changes in the selection to
4687          * disable the OK button whenever "Move to" is not possible
4688          * disbale NEW button whenever New is not possible */
4689         g_signal_connect (*tree_view,
4690                           "folder_selection_changed",
4691                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4692                           win);
4693
4694         /* Listen to clicks on New button */
4695         g_signal_connect (G_OBJECT (new_button), 
4696                           "clicked", 
4697                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4698                           *tree_view);
4699
4700         /* It could happen that we're trying to move a message from a
4701            window (msg window for example) after the main window was
4702            closed, so we can not just get the model of the folder
4703            view */
4704         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4705                 const gchar *visible_id = NULL;
4706
4707                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4708                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4709                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4710                                                MODEST_FOLDER_VIEW(*tree_view));
4711
4712                 visible_id = 
4713                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4714
4715                 /* Show the same account than the one that is shown in the main window */
4716                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4717                                                                              visible_id);
4718         } else {
4719                 const gchar *active_account_name = NULL;
4720                 ModestAccountMgr *mgr = NULL;
4721                 ModestAccountSettings *settings = NULL;
4722                 ModestServerAccountSettings *store_settings = NULL;
4723
4724                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4725                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4726                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4727                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4728
4729                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4730                 mgr = modest_runtime_get_account_mgr ();
4731                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4732
4733                 if (settings) {
4734                         const gchar *store_account_name;
4735                         store_settings = modest_account_settings_get_store_settings (settings);
4736                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4737
4738                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4739                                                                                      store_account_name);
4740                         g_object_unref (store_settings);
4741                         g_object_unref (settings);
4742                 }
4743         }
4744
4745         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4746          *   get_folder_view_from_move_to_dialog 
4747          * (see above) later (needed for focus handling) 
4748          */
4749         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4750
4751         
4752         /* Hide special folders */
4753         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4754
4755 #ifdef MODEST_TOOLKIT_HILDON2
4756         gtk_container_add (GTK_CONTAINER (pannable), *tree_view);
4757         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4758                             pannable, TRUE, TRUE, 0);
4759 #else
4760         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4761         /* Add scroll to dialog */
4762         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4763                             scroll, TRUE, TRUE, 0);
4764 #endif
4765
4766
4767         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4768 #ifndef MODEST_TOOLKIT_GTK
4769         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4770 #else
4771         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4772 #endif
4773
4774         return dialog;
4775 }
4776
4777
4778
4779 /*
4780  * Shows a confirmation dialog to the user when we're moving messages
4781  * from a remote server to the local storage. Returns the dialog
4782  * response. If it's other kind of movement then it always returns
4783  * GTK_RESPONSE_OK
4784  *
4785  * This one is used by the next functions:
4786  *      modest_ui_actions_on_paste                      - commented out
4787  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4788  */
4789 gint
4790 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4791                                              TnyFolder *dest_folder,
4792                                              gboolean delete,
4793                                              TnyList *headers)
4794 {
4795         gint response = GTK_RESPONSE_OK;
4796         TnyAccount *account = NULL;
4797         TnyFolder *src_folder = NULL;
4798         TnyIterator *iter = NULL;
4799         TnyHeader *header = NULL;
4800
4801         /* return with OK if the destination is a remote folder */
4802         if (modest_tny_folder_is_remote_folder (dest_folder))
4803                 return GTK_RESPONSE_OK;
4804
4805         /* Get source folder */
4806         iter = tny_list_create_iterator (headers);
4807         header = TNY_HEADER (tny_iterator_get_current (iter));
4808         if (header) {
4809                 src_folder = tny_header_get_folder (header);
4810                 g_object_unref (header);
4811         }
4812         g_object_unref (iter);
4813
4814         /* if no src_folder, message may be an attahcment */
4815         if (src_folder == NULL) 
4816                 return GTK_RESPONSE_CANCEL;
4817
4818         /* If the source is a local or MMC folder */
4819         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4820                 g_object_unref (src_folder);
4821                 return GTK_RESPONSE_OK;
4822         }
4823
4824         /* Get the account */
4825         account = tny_folder_get_account (src_folder);
4826
4827         /* now if offline we ask the user */
4828         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4829                 response = GTK_RESPONSE_OK;
4830         else
4831                 response = GTK_RESPONSE_CANCEL;
4832
4833         /* Frees */
4834         g_object_unref (src_folder);
4835         g_object_unref (account);
4836
4837         return response;
4838 }
4839
4840 static void
4841 move_to_helper_destroyer (gpointer user_data)
4842 {
4843         MoveToHelper *helper = (MoveToHelper *) user_data;
4844
4845         /* Close the "Pasting" information banner */
4846         if (helper->banner) {
4847                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4848                 g_object_unref (helper->banner);
4849         }
4850         if (gtk_tree_row_reference_valid (helper->reference)) {
4851                 gtk_tree_row_reference_free (helper->reference);
4852                 helper->reference = NULL;
4853         }
4854         g_free (helper);
4855 }
4856
4857 static void
4858 move_to_cb (ModestMailOperation *mail_op, 
4859             gpointer user_data)
4860 {
4861         MoveToHelper *helper = (MoveToHelper *) user_data;
4862
4863         /* Note that the operation could have failed, in that case do
4864            nothing */
4865         if (modest_mail_operation_get_status (mail_op) == 
4866             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4867
4868                 GObject *object = modest_mail_operation_get_source (mail_op);
4869                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4870                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4871
4872                         if (!modest_msg_view_window_select_next_message (self) &&
4873                             !modest_msg_view_window_select_previous_message (self)) {
4874                                 /* No more messages to view, so close this window */
4875                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4876                         }
4877                 } else if (MODEST_IS_MAIN_WINDOW (object) && 
4878                            gtk_tree_row_reference_valid (helper->reference)) {
4879                         GtkWidget *header_view;
4880                         GtkTreePath *path;
4881                         GtkTreeSelection *sel;
4882
4883                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4884                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4885                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4886                         path = gtk_tree_row_reference_get_path (helper->reference);
4887                         /* We need to unselect the previous one
4888                            because we could be copying instead of
4889                            moving */
4890                         gtk_tree_selection_unselect_all (sel);
4891                         gtk_tree_selection_select_path (sel, path);
4892                         gtk_tree_path_free (path);
4893                 }
4894                 g_object_unref (object);
4895         }
4896         /* Destroy the helper */
4897         move_to_helper_destroyer (helper);
4898 }
4899
4900 static void
4901 folder_move_to_cb (ModestMailOperation *mail_op, 
4902                    TnyFolder *new_folder,
4903                    gpointer user_data)
4904 {
4905         GtkWidget *folder_view;
4906         GObject *object;
4907
4908         object = modest_mail_operation_get_source (mail_op);
4909         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4910                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4911         g_object_ref (folder_view);
4912         g_object_unref (object);
4913         move_to_cb (mail_op, user_data);
4914         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4915         g_object_unref (folder_view);
4916 }
4917
4918 static void
4919 msgs_move_to_cb (ModestMailOperation *mail_op, 
4920                  gpointer user_data)
4921 {
4922         move_to_cb (mail_op, user_data);
4923 }
4924
4925 void
4926 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4927                                              gpointer user_data)
4928 {
4929         ModestWindow *main_window = NULL;
4930         
4931         /* Disable next automatic folder selection */
4932         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4933                                                          FALSE); /* don't create */
4934         if (main_window) {
4935                 GObject *win = NULL;
4936                 GtkWidget *folder_view = NULL;
4937         
4938                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4939                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4940                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4941                 
4942                 if (user_data && TNY_IS_FOLDER (user_data)) {
4943                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4944                                                           TNY_FOLDER (user_data), FALSE);
4945                 }
4946
4947                 /* Show notification dialog only if the main window exists */
4948                 win = modest_mail_operation_get_source (mail_op);
4949                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4950                                                         _("mail_in_ui_folder_move_target_error"), 
4951                                                         FALSE);
4952                 if (win)
4953                         g_object_unref (win);
4954         }
4955 }
4956
4957 static void
4958 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4959                        TnyHeader *header, 
4960                        gboolean canceled,
4961                        TnyMsg *msg, 
4962                        GError *err,
4963                        gpointer user_data)
4964 {
4965         TnyList *parts;
4966         TnyIterator *iter;
4967         gint pending_purges = 0;
4968         gboolean some_purged = FALSE;
4969         ModestWindow *win = MODEST_WINDOW (user_data);
4970         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4971
4972         /* If there was any error */
4973         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4974                 modest_window_mgr_unregister_header (mgr, header);
4975                 return;
4976         }
4977
4978         /* Once the message has been retrieved for purging, we check if
4979          * it's all ok for purging */
4980
4981         parts = tny_simple_list_new ();
4982         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4983         iter = tny_list_create_iterator (parts);
4984
4985         while (!tny_iterator_is_done (iter)) {
4986                 TnyMimePart *part;
4987                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4988                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4989                         if (tny_mime_part_is_purged (part))
4990                                 some_purged = TRUE;
4991                         else
4992                                 pending_purges++;
4993                 }
4994
4995                 if (part)
4996                         g_object_unref (part);
4997
4998                 tny_iterator_next (iter);
4999         }
5000         g_object_unref (iter);
5001         
5002
5003         if (pending_purges>0) {
5004                 gint response;
5005                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5006
5007                 if (response == GTK_RESPONSE_OK) {
5008                         GtkWidget *info;
5009                         info =
5010                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
5011                         iter = tny_list_create_iterator (parts);
5012                         while (!tny_iterator_is_done (iter)) {
5013                                 TnyMimePart *part;
5014                                 
5015                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5016                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5017                                         tny_mime_part_set_purged (part);
5018
5019                                 if (part)
5020                                         g_object_unref (part);
5021
5022                                 tny_iterator_next (iter);
5023                         }
5024                         g_object_unref (iter);
5025                         
5026                         tny_msg_rewrite_cache (msg);
5027
5028                         gtk_widget_destroy (info);
5029                 }
5030         }
5031
5032         modest_window_mgr_unregister_header (mgr, header);
5033
5034         g_object_unref (parts);
5035 }
5036
5037 static void
5038 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5039                                                      ModestMainWindow *win)
5040 {
5041         GtkWidget *header_view;
5042         TnyList *header_list;
5043         TnyHeader *header;
5044         TnyHeaderFlags flags;
5045         ModestWindow *msg_view_window =  NULL;
5046         gboolean found;
5047
5048         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5049
5050         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5051                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5052
5053         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5054         if (!header_list) {
5055                 g_warning ("%s: no header selected", __FUNCTION__);
5056                 return;
5057         }
5058         
5059         if (tny_list_get_length (header_list) == 1) {
5060                 TnyIterator *iter = tny_list_create_iterator (header_list);
5061                 header = TNY_HEADER (tny_iterator_get_current (iter));
5062                 g_object_unref (iter);
5063         } else
5064                 return;
5065         
5066         if (!header || !TNY_IS_HEADER(header)) {
5067                 g_warning ("%s: header is not valid", __FUNCTION__);
5068                 return;
5069         }
5070         
5071         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5072                                                           header, &msg_view_window);
5073         flags = tny_header_get_flags (header);
5074         if (!(flags & TNY_HEADER_FLAG_CACHED))
5075                 return;
5076         if (found) {
5077                 if (msg_view_window != NULL) 
5078                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5079                 else {
5080                         /* do nothing; uid was registered before, so window is probably on it's way */
5081                         g_warning ("debug: header %p has already been registered", header);
5082                 }
5083         } else {
5084                 ModestMailOperation *mail_op = NULL;
5085                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5086                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5087                                                                          modest_ui_actions_disk_operations_error_handler,
5088                                                                          NULL, NULL);
5089                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5090                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5091                 
5092                 g_object_unref (mail_op);
5093         }
5094         if (header)
5095                 g_object_unref (header);
5096         if (header_list)
5097                 g_object_unref (header_list);
5098 }
5099
5100 /*
5101  * Checks if we need a connection to do the transfer and if the user
5102  * wants to connect to complete it
5103  */
5104 void
5105 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5106                                        TnyFolderStore *src_folder,
5107                                        TnyList *headers,
5108                                        TnyFolder *dst_folder,
5109                                        gboolean delete_originals,
5110                                        gboolean *need_connection,
5111                                        gboolean *do_xfer)
5112 {
5113         TnyAccount *src_account;
5114         gint uncached_msgs = 0;
5115
5116         uncached_msgs = header_list_count_uncached_msgs (headers);
5117
5118         /* We don't need any further check if
5119          *
5120          * 1- the source folder is local OR
5121          * 2- the device is already online
5122          */
5123         if (!modest_tny_folder_store_is_remote (src_folder) ||
5124             tny_device_is_online (modest_runtime_get_device())) {
5125                 *need_connection = FALSE;
5126                 *do_xfer = TRUE;
5127                 return;
5128         }
5129
5130         /* We must ask for a connection when
5131          *
5132          *   - the message(s) is not already cached   OR 
5133          *   - the message(s) is cached but the leave_on_server setting
5134          * is FALSE (because we need to sync the source folder to
5135          * delete the message from the server (for IMAP we could do it
5136          * offline, it'll take place the next time we get a
5137          * connection)
5138          */
5139         src_account = get_account_from_folder_store (src_folder);
5140         if (uncached_msgs > 0) {
5141                 guint num_headers;
5142                 const gchar *msg;
5143
5144                 *need_connection = TRUE;
5145                 num_headers = tny_list_get_length (headers);
5146                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5147
5148                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5149                     GTK_RESPONSE_CANCEL) {
5150                         *do_xfer = FALSE;
5151                 } else {
5152                         *do_xfer = TRUE;
5153                 }
5154         } else {
5155                 /* The transfer is possible and the user wants to */
5156                 *do_xfer = TRUE;
5157
5158                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5159                         const gchar *account_name;
5160                         gboolean leave_on_server;
5161                         
5162                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5163                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5164                                                                                   account_name);
5165                         
5166                         if (leave_on_server == TRUE) {
5167                                 *need_connection = FALSE;
5168                         } else {
5169                                 *need_connection = TRUE;
5170                         }
5171                 } else {
5172                         *need_connection = FALSE;
5173                 }
5174         }
5175
5176         /* Frees */
5177         g_object_unref (src_account);
5178 }
5179
5180 static void
5181 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5182                              gpointer user_data)
5183 {
5184         ModestWindow *main_window = NULL;
5185
5186         /* Disable next automatic folder selection */
5187         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5188                                                          FALSE); /* don't create */
5189         if (main_window) {
5190                 GObject *win = modest_mail_operation_get_source (mail_op);
5191                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5192                                                         _("mail_in_ui_folder_move_target_error"), 
5193                                                         FALSE);
5194                 if (win)
5195                         g_object_unref (win);
5196         }
5197         move_to_helper_destroyer (user_data);
5198 }
5199
5200 typedef struct {
5201         TnyFolderStore *dst_folder;
5202         TnyList *headers;
5203 } XferMsgsHelper;
5204
5205 /**
5206  * Utility function that transfer messages from both the main window
5207  * and the msg view window when using the "Move to" dialog
5208  */
5209 static void
5210 xfer_messages_performer  (gboolean canceled, 
5211                           GError *err,
5212                           GtkWindow *parent_window, 
5213                           TnyAccount *account, 
5214                           gpointer user_data)
5215 {
5216         ModestWindow *win = MODEST_WINDOW (parent_window);
5217         TnyAccount *dst_account = NULL;
5218         gboolean dst_forbids_message_add = FALSE;
5219         XferMsgsHelper *helper;
5220         MoveToHelper *movehelper;
5221         ModestMailOperation *mail_op;
5222
5223         helper = (XferMsgsHelper *) user_data;
5224
5225         if (canceled || err) {
5226                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5227                         /* Show the proper error message */
5228                         modest_ui_actions_on_account_connection_error (parent_window, account);
5229                 }
5230                 goto end;
5231         }
5232
5233         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5234
5235         /* tinymail will return NULL for local folders it seems */
5236         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5237                                                                                   modest_tny_account_get_protocol_type (dst_account),
5238                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5239         g_object_unref (dst_account);
5240
5241         if (dst_forbids_message_add) {
5242                 modest_platform_information_banner (GTK_WIDGET (win),
5243                                                     NULL,
5244                                                     ngettext("mail_in_ui_folder_move_target_error",
5245                                                              "mail_in_ui_folder_move_targets_error",
5246                                                              tny_list_get_length (helper->headers)));
5247                 goto end;
5248         }
5249
5250         movehelper = g_new0 (MoveToHelper, 1);
5251         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5252                                                                _CS("ckct_nw_pasting"));
5253         if (movehelper->banner != NULL)  {
5254                 g_object_ref (movehelper->banner);
5255                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5256         }
5257
5258         if (MODEST_IS_MAIN_WINDOW (win)) {
5259                 GtkWidget *header_view = 
5260                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5261                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5262                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5263         }
5264
5265         /* Perform the mail operation */
5266         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5267                                                                  xfer_messages_error_handler,
5268                                                                  movehelper, NULL);
5269         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5270                                          mail_op);
5271
5272         modest_mail_operation_xfer_msgs (mail_op, 
5273                                          helper->headers,
5274                                          TNY_FOLDER (helper->dst_folder),
5275                                          TRUE,
5276                                          msgs_move_to_cb,
5277                                          movehelper);
5278
5279         g_object_unref (G_OBJECT (mail_op));
5280  end:
5281         g_object_unref (helper->dst_folder);
5282         g_object_unref (helper->headers);
5283         g_slice_free (XferMsgsHelper, helper);
5284 }
5285
5286 typedef struct {
5287         TnyFolder *src_folder;
5288         TnyFolderStore *dst_folder;
5289         gboolean delete_original;
5290         GtkWidget *folder_view;
5291 } MoveFolderInfo;
5292
5293 static void
5294 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5295                 TnyAccount *account, gpointer user_data)
5296 {
5297         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5298         GtkTreeSelection *sel;
5299         ModestMailOperation *mail_op = NULL;
5300         
5301         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5302                 g_object_unref (G_OBJECT (info->src_folder));
5303                 g_object_unref (G_OBJECT (info->dst_folder));
5304                 g_free (info);
5305                 return;
5306         }
5307         
5308         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5309         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5310                         _CS("ckct_nw_pasting"));
5311         if (helper->banner != NULL)  {
5312                 g_object_ref (helper->banner);
5313                 gtk_widget_show (GTK_WIDGET(helper->banner));
5314         }
5315         /* Clean folder on header view before moving it */
5316         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5317         gtk_tree_selection_unselect_all (sel);
5318
5319         /* Let gtk events run. We need that the folder
5320            view frees its reference to the source
5321            folder *before* issuing the mail operation
5322            so we need the signal handler of selection
5323            changed to happen before the mail
5324            operation 
5325         while (gtk_events_pending ())
5326                 gtk_main_iteration ();   */
5327
5328         mail_op =
5329                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5330                                 modest_ui_actions_move_folder_error_handler,
5331                                 info->src_folder, NULL);
5332         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5333                         mail_op);
5334
5335         /* Select *after* the changes */
5336         /* TODO: this function hangs UI after transfer */ 
5337         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5338         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5339
5340         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5341                                           TNY_FOLDER (info->dst_folder), TRUE);
5342         modest_mail_operation_xfer_folder (mail_op,
5343                         TNY_FOLDER (info->src_folder),
5344                         info->dst_folder,
5345                         info->delete_original, 
5346                         folder_move_to_cb, 
5347                         helper);
5348         g_object_unref (G_OBJECT (info->src_folder));
5349
5350         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5351         /* } */
5352         
5353         /* Unref mail operation */
5354         g_object_unref (G_OBJECT (mail_op));
5355         g_object_unref (G_OBJECT (info->dst_folder));
5356         g_free (user_data);
5357 }
5358
5359 static TnyAccount *
5360 get_account_from_folder_store (TnyFolderStore *folder_store) 
5361 {
5362         if (TNY_IS_ACCOUNT (folder_store))
5363                 return g_object_ref (folder_store);
5364         else
5365                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5366 }
5367
5368 /*
5369  * UI handler for the "Move to" action when invoked from the
5370  * ModestMainWindow
5371  */
5372 static void 
5373 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5374                                           GtkWidget *folder_view,
5375                                           TnyFolderStore *dst_folder,
5376                                           ModestMainWindow *win)
5377 {
5378         ModestHeaderView *header_view = NULL;
5379         TnyFolderStore *src_folder = NULL;
5380
5381         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5382
5383         /* Get the source folder */
5384         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5385
5386         /* Get header view */
5387         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5388
5389         /* Get folder or messages to transfer */
5390         if (gtk_widget_is_focus (folder_view)) {
5391                 gboolean do_xfer = TRUE;
5392
5393                 /* Allow only to transfer folders to the local root folder */
5394                 if (TNY_IS_ACCOUNT (dst_folder) && 
5395                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5396                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5397                         do_xfer = FALSE;
5398                 } else if (!TNY_IS_FOLDER (src_folder)) {
5399                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5400                         do_xfer = FALSE;
5401                 }
5402
5403                 if (do_xfer) {                  
5404                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5405                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5406
5407                         info->src_folder = g_object_ref (src_folder);
5408                         info->dst_folder = g_object_ref (dst_folder);
5409                         info->delete_original = TRUE;
5410                         info->folder_view = folder_view;
5411
5412                         connect_info->callback = on_move_folder_cb;
5413                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5414                         connect_info->data = info;
5415
5416                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5417                                                                    TNY_FOLDER_STORE (src_folder), 
5418                                                                    connect_info);
5419                 }
5420         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5421                 TnyList *headers;
5422
5423                 headers = modest_header_view_get_selected_headers(header_view);
5424
5425                 /* Transfer the messages */
5426                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5427                                                             headers, TNY_FOLDER (dst_folder));
5428
5429                 g_object_unref (headers);
5430         }
5431
5432         /* Frees */
5433         g_object_unref (src_folder);
5434 }
5435
5436
5437 void
5438 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5439                                             TnyFolder *src_folder,
5440                                             TnyList *headers,
5441                                             TnyFolder *dst_folder)
5442 {
5443         gboolean need_connection = TRUE;
5444         gboolean do_xfer = TRUE;
5445         XferMsgsHelper *helper;
5446
5447         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5448         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5449         g_return_if_fail (TNY_IS_LIST (headers));
5450         
5451         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5452                                                headers, TNY_FOLDER (dst_folder),
5453                                                TRUE, &need_connection, 
5454                                                &do_xfer);
5455
5456         /* If we don't want to transfer just return */
5457         if (!do_xfer)
5458                 return;
5459
5460         /* Create the helper */
5461         helper = g_slice_new (XferMsgsHelper);
5462         helper->dst_folder = g_object_ref (dst_folder);
5463         helper->headers = g_object_ref (headers);
5464
5465         if (need_connection) {
5466                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5467                 connect_info->callback = xfer_messages_performer;
5468                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5469                 connect_info->data = helper;
5470                 
5471                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5472                                                            TNY_FOLDER_STORE (src_folder), 
5473                                                            connect_info);
5474         } else {
5475                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5476                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5477                                          src_account, helper);
5478                 g_object_unref (src_account);
5479         }
5480 }
5481
5482 /*
5483  * UI handler for the "Move to" action when invoked from the
5484  * ModestMsgViewWindow
5485  */
5486 static void 
5487 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5488                                               TnyFolderStore *dst_folder,
5489                                               ModestMsgViewWindow *win)
5490 {
5491         TnyList *headers = NULL;
5492         TnyHeader *header = NULL;
5493         TnyFolder *src_folder = NULL;
5494
5495         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5496
5497         /* Create header list */
5498         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5499         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5500         headers = tny_simple_list_new ();
5501         tny_list_append (headers, G_OBJECT (header));
5502
5503         /* Transfer the messages */
5504         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5505                                                     TNY_FOLDER (dst_folder));
5506
5507         /* Frees */
5508         g_object_unref (src_folder);
5509         g_object_unref (header);
5510         g_object_unref (headers);
5511 }
5512
5513 void 
5514 modest_ui_actions_on_move_to (GtkAction *action, 
5515                               ModestWindow *win)
5516 {
5517         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5518         gint result = 0;
5519         TnyFolderStore *dst_folder = NULL;
5520         ModestMainWindow *main_window;
5521
5522         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5523                           MODEST_IS_MSG_VIEW_WINDOW (win));
5524
5525         /* Get the main window if exists */
5526         if (MODEST_IS_MAIN_WINDOW (win))
5527                 main_window = MODEST_MAIN_WINDOW (win);
5528         else
5529                 main_window = 
5530                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5531                                                                                FALSE)); /* don't create */
5532
5533         /* Get the folder view widget if exists */
5534         if (main_window)
5535                 folder_view = modest_main_window_get_child_widget (main_window,
5536                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5537         else
5538                 folder_view = NULL;
5539
5540         /* Create and run the dialog */
5541         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5542         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5543         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) win);
5544         result = gtk_dialog_run (GTK_DIALOG(dialog));
5545         g_object_ref (tree_view);
5546         gtk_widget_destroy (dialog);
5547
5548         if (result != GTK_RESPONSE_ACCEPT)
5549                 return;
5550
5551         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5552         /* Do window specific stuff */
5553         if (MODEST_IS_MAIN_WINDOW (win)) {
5554                 modest_ui_actions_on_main_window_move_to (action,
5555                                 folder_view,
5556                                 dst_folder,
5557                                 MODEST_MAIN_WINDOW (win));
5558         } else {
5559                 modest_ui_actions_on_msg_view_window_move_to (action,
5560                                 dst_folder,
5561                                 MODEST_MSG_VIEW_WINDOW (win));
5562         }
5563
5564         if (dst_folder)
5565                 g_object_unref (dst_folder);
5566 }
5567
5568 /*
5569  * Calls #HeadersFunc for each header already selected in the main
5570  * window or the message currently being shown in the msg view window
5571  */
5572 static void
5573 do_headers_action (ModestWindow *win, 
5574                    HeadersFunc func,
5575                    gpointer user_data)
5576 {
5577         TnyList *headers_list = NULL;
5578         TnyIterator *iter = NULL;
5579         TnyHeader *header = NULL;
5580         TnyFolder *folder = NULL;
5581
5582         /* Get headers */
5583         headers_list = get_selected_headers (win);
5584         if (!headers_list)
5585                 return;
5586
5587         /* Get the folder */
5588         iter = tny_list_create_iterator (headers_list);
5589         header = TNY_HEADER (tny_iterator_get_current (iter));
5590         if (header) {
5591                 folder = tny_header_get_folder (header);
5592                 g_object_unref (header);
5593         }
5594
5595         /* Call the function for each header */
5596         while (!tny_iterator_is_done (iter)) {
5597                 header = TNY_HEADER (tny_iterator_get_current (iter));
5598                 func (header, win, user_data);
5599                 g_object_unref (header);
5600                 tny_iterator_next (iter);
5601         }
5602
5603         /* Trick: do a poke status in order to speed up the signaling
5604            of observers */
5605         tny_folder_poke_status (folder);
5606
5607         /* Frees */
5608         g_object_unref (folder);
5609         g_object_unref (iter);
5610         g_object_unref (headers_list);
5611 }
5612
5613 void 
5614 modest_ui_actions_view_attachment (GtkAction *action,
5615                                    ModestWindow *window)
5616 {
5617         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5618                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5619         } else {
5620                 /* not supported window for this action */
5621                 g_return_if_reached ();
5622         }
5623 }
5624
5625 void
5626 modest_ui_actions_save_attachments (GtkAction *action,
5627                                     ModestWindow *window)
5628 {
5629         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5630
5631                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5632                         return;
5633
5634                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5635         } else {
5636                 /* not supported window for this action */
5637                 g_return_if_reached ();
5638         }
5639 }
5640
5641 void
5642 modest_ui_actions_remove_attachments (GtkAction *action,
5643                                       ModestWindow *window)
5644 {
5645         if (MODEST_IS_MAIN_WINDOW (window)) {
5646                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5647         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5648                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5649         } else {
5650                 /* not supported window for this action */
5651                 g_return_if_reached ();
5652         }
5653 }
5654
5655 void 
5656 modest_ui_actions_on_settings (GtkAction *action, 
5657                                ModestWindow *win)
5658 {
5659         GtkWidget *dialog;
5660
5661         dialog = modest_platform_get_global_settings_dialog ();
5662         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5663         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5664         gtk_widget_show_all (dialog);
5665
5666         gtk_dialog_run (GTK_DIALOG (dialog));
5667
5668         gtk_widget_destroy (dialog);
5669 }
5670
5671 void 
5672 modest_ui_actions_on_help (GtkAction *action, 
5673                            GtkWindow *win)
5674 {
5675         const gchar *help_id;
5676
5677         g_return_if_fail (win && GTK_IS_WINDOW(win));
5678         
5679         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5680
5681         if (help_id)
5682                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5683 }
5684
5685 void 
5686 modest_ui_actions_on_csm_help (GtkAction *action, 
5687                                GtkWindow *win)
5688 {
5689         const gchar* help_id = NULL;
5690         GtkWidget *folder_view;
5691         TnyFolderStore *folder_store;
5692
5693         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5694
5695         /* Get selected folder */
5696         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5697                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5698         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5699
5700         /* Switch help_id */
5701         if (folder_store && TNY_IS_FOLDER (folder_store))
5702                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5703
5704         if (folder_store)
5705                 g_object_unref (folder_store);
5706
5707         if (help_id)
5708                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5709         else
5710                 modest_ui_actions_on_help (action, win);
5711 }
5712
5713 static void     
5714 retrieve_contents_cb (ModestMailOperation *mail_op, 
5715                       TnyHeader *header, 
5716                       gboolean canceled,
5717                       TnyMsg *msg,
5718                       GError *err,
5719                       gpointer user_data)
5720 {
5721         /* We only need this callback to show an error in case of
5722            memory low condition */
5723         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5724 }
5725
5726 static void
5727 retrieve_msg_contents_performer (gboolean canceled, 
5728                                  GError *err,
5729                                  GtkWindow *parent_window, 
5730                                  TnyAccount *account, 
5731                                  gpointer user_data)
5732 {
5733         ModestMailOperation *mail_op;
5734         TnyList *headers = TNY_LIST (user_data);
5735
5736         if (err || canceled) {
5737                 check_memory_full_error ((GtkWidget *) parent_window, err);
5738                 goto out;
5739         }
5740
5741         /* Create mail operation */
5742         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5743                                                                  modest_ui_actions_disk_operations_error_handler, 
5744                                                                  NULL, NULL);
5745         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5746         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5747
5748         /* Frees */
5749         g_object_unref (mail_op);
5750  out:
5751         g_object_unref (headers);
5752         g_object_unref (account);
5753 }
5754
5755 void 
5756 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5757                                             ModestWindow *window)
5758 {
5759         TnyList *headers = NULL;
5760         TnyAccount *account = NULL;
5761         TnyIterator *iter = NULL;
5762         TnyHeader *header = NULL;
5763         TnyFolder *folder = NULL;
5764
5765         /* Get headers */
5766         headers = get_selected_headers (window);
5767         if (!headers)
5768                 return;
5769
5770         /* Pick the account */
5771         iter = tny_list_create_iterator (headers);
5772         header = TNY_HEADER (tny_iterator_get_current (iter));
5773         folder = tny_header_get_folder (header);
5774         account = tny_folder_get_account (folder);
5775         g_object_unref (folder);
5776         g_object_unref (header);
5777         g_object_unref (iter);
5778
5779         /* Connect and perform the message retrieval */
5780         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5781                                              g_object_ref (account), 
5782                                              retrieve_msg_contents_performer, 
5783                                              g_object_ref (headers));
5784
5785         /* Frees */
5786         g_object_unref (account);
5787         g_object_unref (headers);
5788 }
5789
5790 void
5791 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5792 {
5793         g_return_if_fail (MODEST_IS_WINDOW (window));
5794
5795         /* Update dimmed */
5796         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5797 }
5798
5799 void
5800 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5801 {
5802         g_return_if_fail (MODEST_IS_WINDOW (window));
5803
5804         /* Update dimmed */
5805         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5806 }
5807
5808 void
5809 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5810                                           ModestWindow *window)
5811 {
5812         g_return_if_fail (MODEST_IS_WINDOW (window));
5813         
5814         /* Update dimmed */
5815         modest_ui_actions_check_menu_dimming_rules (window);
5816 }
5817
5818 void
5819 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5820                                           ModestWindow *window)
5821 {
5822         g_return_if_fail (MODEST_IS_WINDOW (window));
5823
5824         /* Update dimmed */
5825         modest_ui_actions_check_menu_dimming_rules (window);
5826 }
5827
5828 void
5829 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5830                                           ModestWindow *window)
5831 {
5832         g_return_if_fail (MODEST_IS_WINDOW (window));
5833
5834         /* Update dimmed */
5835         modest_ui_actions_check_menu_dimming_rules (window);
5836 }
5837
5838 void
5839 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5840                                             ModestWindow *window)
5841 {
5842         g_return_if_fail (MODEST_IS_WINDOW (window));
5843
5844         /* Update dimmed */
5845         modest_ui_actions_check_menu_dimming_rules (window);
5846 }
5847
5848 void
5849 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5850                                           ModestWindow *window)
5851 {
5852         g_return_if_fail (MODEST_IS_WINDOW (window));
5853
5854         /* Update dimmed */
5855         modest_ui_actions_check_menu_dimming_rules (window);
5856 }
5857
5858 void
5859 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5860                                           ModestWindow *window)
5861 {
5862         g_return_if_fail (MODEST_IS_WINDOW (window));
5863
5864         /* Update dimmed */
5865         modest_ui_actions_check_menu_dimming_rules (window);
5866 }
5867
5868 void
5869 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5870                                                  ModestWindow *window)
5871 {
5872         g_return_if_fail (MODEST_IS_WINDOW (window));
5873
5874         /* Update dimmed */
5875         modest_ui_actions_check_menu_dimming_rules (window);
5876 }
5877
5878 void
5879 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5880                                                      ModestWindow *window)
5881 {
5882         g_return_if_fail (MODEST_IS_WINDOW (window));
5883
5884         /* Update dimmed */
5885         modest_ui_actions_check_menu_dimming_rules (window);
5886 }
5887
5888 void
5889 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5890                                                      ModestWindow *window)
5891 {
5892         g_return_if_fail (MODEST_IS_WINDOW (window));
5893
5894         /* Update dimmed */
5895         modest_ui_actions_check_menu_dimming_rules (window);
5896 }
5897
5898 void
5899 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5900 {
5901         g_return_if_fail (MODEST_IS_WINDOW (window));
5902
5903         /* we check for low-mem; in that case, show a warning, and don't allow
5904          * searching
5905          */
5906         if (modest_platform_check_memory_low (window, TRUE))
5907                 return;
5908         
5909         modest_platform_show_search_messages (GTK_WINDOW (window));
5910 }
5911
5912 void     
5913 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5914 {
5915         g_return_if_fail (MODEST_IS_WINDOW (win));
5916
5917
5918         /* we check for low-mem; in that case, show a warning, and don't allow
5919          * for the addressbook
5920          */
5921         if (modest_platform_check_memory_low (win, TRUE))
5922                 return;
5923
5924
5925         modest_platform_show_addressbook (GTK_WINDOW (win));
5926 }
5927
5928
5929 void
5930 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5931                                           ModestWindow *window)
5932 {
5933         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5934
5935         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5936 }
5937
5938 static void 
5939 on_send_receive_finished (ModestMailOperation  *mail_op, 
5940                            gpointer user_data)
5941 {
5942         GtkWidget *header_view, *folder_view;
5943         TnyFolderStore *folder_store;
5944         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5945
5946         /* Set send/receive operation finished */       
5947         modest_main_window_notify_send_receive_completed (main_win);
5948
5949         /* Don't refresh the current folder if there were any errors */
5950         if (modest_mail_operation_get_status (mail_op) !=
5951             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5952                 return;
5953         
5954         /* Refresh the current folder if we're viewing a window. We do
5955            this because the user won't be able to see the new mails in
5956            the selected folder after a Send&Receive because it only
5957            performs a poke_status, i.e, only the number of read/unread
5958            messages is updated, but the new headers are not
5959            downloaded */
5960         folder_view = modest_main_window_get_child_widget (main_win, 
5961                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5962         if (!folder_view)
5963                 return;
5964
5965         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5966         
5967         /* Do not need to refresh INBOX again because the
5968            update_account does it always automatically */
5969         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5970             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5971                 ModestMailOperation *refresh_op;
5972
5973                 header_view = modest_main_window_get_child_widget (main_win,
5974                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5975                 
5976                 /* We do not need to set the contents style
5977                    because it hasn't changed. We also do not
5978                    need to save the widget status. Just force
5979                    a refresh */
5980                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5981                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5982                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5983                                                       folder_refreshed_cb, main_win);
5984                 g_object_unref (refresh_op);
5985         }
5986         
5987         if (folder_store)
5988                 g_object_unref (folder_store);
5989 }
5990
5991
5992 void 
5993 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5994                                                 TnyHeader *header, 
5995                                                 TnyMsg *msg, 
5996                                                 GError *err, 
5997                                                 gpointer user_data)
5998 {
5999         const gchar* server_name = NULL;
6000         TnyTransportAccount *server_account;
6001         gchar *message = NULL;
6002
6003         /* Don't show anything if the user cancelled something or the
6004          * send receive request is not interactive. Authentication
6005          * errors are managed by the account store so no need to show
6006          * a dialog here again */
6007         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6008             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6009             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6010                 return;
6011
6012
6013         /* Get the server name: */
6014         server_account = 
6015                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
6016         if (server_account)
6017                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
6018         else
6019                 g_return_if_reached ();
6020
6021         /* Show the appropriate message text for the GError: */
6022         switch (err->code) {
6023         case TNY_SERVICE_ERROR_CONNECT:
6024                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6025                 break;
6026         case TNY_SERVICE_ERROR_SEND:
6027                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6028                 break;
6029         case TNY_SERVICE_ERROR_UNAVAILABLE:
6030                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6031                 break;
6032         default:
6033                 g_warning ("%s: unexpected ERROR %d",
6034                            __FUNCTION__, err->code);
6035                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6036                 break;  
6037         }
6038
6039         modest_platform_run_information_dialog (NULL, message, FALSE);
6040         g_free (message);
6041         g_object_unref (server_account);
6042 }
6043
6044 void
6045 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6046                                                 gchar *msg_id, 
6047                                                 guint status,
6048                                                 gpointer user_data)
6049 {
6050         ModestMainWindow *main_window = NULL;
6051         ModestWindowMgr *mgr = NULL;
6052         GtkWidget *folder_view = NULL, *header_view = NULL;
6053         TnyFolderStore *selected_folder = NULL;
6054         TnyFolderType folder_type;
6055
6056         mgr = modest_runtime_get_window_mgr ();
6057         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6058                                                                              FALSE));/* don't create */
6059         if (!main_window)
6060                 return;
6061
6062         /* Check if selected folder is OUTBOX */
6063         folder_view = modest_main_window_get_child_widget (main_window,
6064                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6065         header_view = modest_main_window_get_child_widget (main_window,
6066                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6067
6068         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6069         if (!TNY_IS_FOLDER (selected_folder)) 
6070                 goto frees;
6071
6072         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6073 #if GTK_CHECK_VERSION(2, 8, 0) 
6074         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6075         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6076                 GtkTreeViewColumn *tree_column;
6077
6078                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6079                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6080                 if (tree_column)
6081                         gtk_tree_view_column_queue_resize (tree_column);
6082         }
6083 #else
6084         gtk_widget_queue_draw (header_view);
6085 #endif          
6086
6087         /* Rerun dimming rules, because the message could become deletable for example */
6088         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6089                                                  MODEST_DIMMING_RULES_TOOLBAR);
6090         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6091                                                  MODEST_DIMMING_RULES_MENU);
6092         
6093         /* Free */
6094  frees:
6095         if (selected_folder != NULL)
6096                 g_object_unref (selected_folder);
6097 }
6098
6099 void 
6100 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6101                                                TnyAccount *account)
6102 {
6103         ModestProtocolType protocol_type;
6104         ModestProtocol *protocol;
6105         gchar *error_note = NULL;
6106         
6107         protocol_type = modest_tny_account_get_protocol_type (account);
6108         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6109                                                                   protocol_type);
6110
6111         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6112         if (error_note == NULL) {
6113                 g_warning ("%s: This should not be reached", __FUNCTION__);
6114         } else {
6115                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6116                 g_free (error_note);
6117         }
6118 }
6119
6120 gchar *
6121 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6122 {
6123         gchar *msg = NULL;
6124         gchar *subject;
6125         TnyFolderStore *folder = NULL;
6126         TnyAccount *account = NULL;
6127         ModestProtocolType proto;
6128         ModestProtocol *protocol;
6129         TnyHeader *header = NULL;
6130
6131         if (MODEST_IS_MAIN_WINDOW (win)) {
6132                 GtkWidget *header_view;
6133                 TnyList* headers = NULL;
6134                 TnyIterator *iter;
6135                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6136                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6137                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6138                 if (!headers || tny_list_get_length (headers) == 0) {
6139                         if (headers)
6140                                 g_object_unref (headers);
6141                         return NULL;
6142                 }
6143                 iter = tny_list_create_iterator (headers);
6144                 header = TNY_HEADER (tny_iterator_get_current (iter));
6145                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6146                 g_object_unref (iter);
6147                 g_object_unref (headers);
6148         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6149                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6150                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6151         }
6152
6153         /* Get the account type */
6154         account = tny_folder_get_account (TNY_FOLDER (folder));
6155         proto = modest_tny_account_get_protocol_type (account);
6156         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6157                                                                   proto);
6158
6159         subject = tny_header_dup_subject (header);
6160         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6161         if (subject)
6162                 g_free (subject);
6163         if (msg == NULL) {
6164                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6165         }
6166
6167         /* Frees */
6168         g_object_unref (account);
6169         g_object_unref (folder);
6170         g_object_unref (header);
6171
6172         return msg;
6173 }