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