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