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