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