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