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