48d8291264a8d673a97e3a6c154a12d7726e0993
[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-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard-dialog.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 typedef struct _GetMsgAsyncHelper {     
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;     
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         GtkWidget *parent_window;
105 } ReplyForwardHelper;
106
107 typedef struct _MoveToHelper {
108         GtkTreeRowReference *reference;
109         GtkWidget *banner;
110 } MoveToHelper;
111
112 typedef struct _PasteAsAttachmentHelper {
113         ModestMsgEditWindow *window;
114         GtkWidget *banner;
115 } PasteAsAttachmentHelper;
116
117
118 /*
119  * The do_headers_action uses this kind of functions to perform some
120  * action to each member of a list of headers
121  */
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
123
124 static void     do_headers_action     (ModestWindow *win, 
125                                        HeadersFunc func,
126                                        gpointer user_data);
127
128 static void     open_msg_cb            (ModestMailOperation *mail_op, 
129                                         TnyHeader *header, 
130                                         gboolean canceled,
131                                         TnyMsg *msg,
132                                         GError *err,
133                                         gpointer user_data);
134
135 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
136                                         TnyHeader *header, 
137                                         gboolean canceled,
138                                         TnyMsg *msg,
139                                         GError *err,
140                                         gpointer user_data);
141
142 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
143
144 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
145                                         TnyFolder *folder, 
146                                         gpointer user_data);
147
148 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
149                                           gpointer user_data);
150
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
152
153 static gboolean connect_to_get_msg (ModestWindow *win,
154                                     gint num_of_uncached_msgs,
155                                     TnyAccount *account);
156
157 static gboolean remote_folder_is_pop (TnyFolderStore *folder);
158
159 static void     do_create_folder (GtkWindow *window, 
160                                   TnyFolderStore *parent_folder, 
161                                   const gchar *suggested_name);
162
163 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
164
165 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
166
167 static void transfer_messages_helper (GtkWindow *win,
168                                       TnyFolder *src_folder,
169                                       TnyList *headers,
170                                       TnyFolder *dst_folder);
171
172 /*
173  * This function checks whether a TnyFolderStore is a pop account
174  */
175 static gboolean
176 remote_folder_is_pop (TnyFolderStore *folder)
177 {
178         const gchar *proto = NULL;
179         TnyAccount *account = NULL;
180
181         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
182         
183         account = get_account_from_folder_store (folder);
184         proto = tny_account_get_proto (account);
185         g_object_unref (account);
186
187         return (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
188 }
189
190 /* FIXME: this should be merged with the similar code in modest-account-view-window */
191 /* Show the account creation wizard dialog.
192  * returns: TRUE if an account was created. FALSE if the user cancelled.
193  */
194 gboolean
195 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
196 {
197         gboolean result = FALSE;        
198         GtkWindow *dialog, *wizard;
199         gint dialog_response;
200
201         /* Show the easy-setup wizard: */       
202         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
203         if (dialog) {
204                 /* old wizard is active already; 
205                  */
206                 gtk_window_present (GTK_WINDOW(dialog));
207                 return FALSE;
208         }
209         
210
211         /* there is no such wizard yet */       
212         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
213         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
214
215         /* always present a main window in the background 
216          * we do it here, so we cannot end up with two wizards (as this
217          * function might be called in modest_window_mgr_get_main_window as well */
218         if (!win) 
219                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
220                                                          TRUE);  /* create if not existent */
221         
222         /* make sure the mainwindow is visible */
223         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
224         gtk_widget_show_all (GTK_WIDGET(win));
225         gtk_window_present (GTK_WINDOW(win));
226         
227         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
228         gtk_widget_destroy (GTK_WIDGET (wizard));
229         if (gtk_events_pending ())
230                 gtk_main_iteration ();
231
232         if (dialog_response == GTK_RESPONSE_CANCEL) {
233                 result = FALSE;
234         } else {
235                 /* Check whether an account was created: */
236                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
237         }
238         return result;
239 }
240
241
242 void   
243 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
244 {
245         GtkWidget *about;
246         const gchar *authors[] = {
247                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
248                 NULL
249         };
250         about = gtk_about_dialog_new ();
251         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
252         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
253         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
254                                         _("Copyright (c) 2006, Nokia Corporation\n"
255                                           "All rights reserved."));
256         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
257                                        _("a modest e-mail client\n\n"
258                                          "design and implementation: Dirk-Jan C. Binnema\n"
259                                          "contributions from the fine people at KC and Ig\n"
260                                          "uses the tinymail email framework written by Philip van Hoof"));
261         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
262         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
263         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
264         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
265         
266         gtk_dialog_run (GTK_DIALOG (about));
267         gtk_widget_destroy(about);
268 }
269
270 /*
271  * Gets the list of currently selected messages. If the win is the
272  * main window, then it returns a newly allocated list of the headers
273  * selected in the header view. If win is the msg view window, then
274  * the value returned is a list with just a single header.
275  *
276  * The caller of this funcion must free the list.
277  */
278 static TnyList *
279 get_selected_headers (ModestWindow *win)
280 {
281         if (MODEST_IS_MAIN_WINDOW(win)) {
282                 GtkWidget *header_view;         
283                 
284                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
285                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
286                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
287                 
288         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
289                 /* for MsgViewWindows, we simply return a list with one element */
290                 TnyHeader *header;
291                 TnyList *list = NULL;
292                 
293                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
294                 if (header != NULL) {
295                         list = tny_simple_list_new ();
296                         tny_list_prepend (list, G_OBJECT(header));
297                         g_object_unref (G_OBJECT(header));
298                 }
299
300                 return list;
301
302         } else
303                 return NULL;
304 }
305
306 static GtkTreeRowReference *
307 get_next_after_selected_headers (ModestHeaderView *header_view)
308 {
309         GtkTreeSelection *sel;
310         GList *selected_rows, *node;
311         GtkTreePath *path;
312         GtkTreeRowReference *result;
313         GtkTreeModel *model;
314
315         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
316         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
317         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
318
319         if (selected_rows == NULL)
320                 return NULL;
321
322         node = g_list_last (selected_rows);
323         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
324         gtk_tree_path_next (path);
325
326         result = gtk_tree_row_reference_new (model, path);
327
328         gtk_tree_path_free (path);
329         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
330         g_list_free (selected_rows);
331
332         return result;
333 }
334
335 static void
336 headers_action_mark_as_read (TnyHeader *header,
337                              ModestWindow *win,
338                              gpointer user_data)
339 {
340         TnyHeaderFlags flags;
341
342         g_return_if_fail (TNY_IS_HEADER(header));
343
344         flags = tny_header_get_flags (header);
345         if (flags & TNY_HEADER_FLAG_SEEN) return;
346         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
347 }
348
349 static void
350 headers_action_mark_as_unread (TnyHeader *header,
351                                ModestWindow *win,
352                                gpointer user_data)
353 {
354         TnyHeaderFlags flags;
355
356         g_return_if_fail (TNY_IS_HEADER(header));
357
358         flags = tny_header_get_flags (header);
359         if (flags & TNY_HEADER_FLAG_SEEN)  {
360                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
361         }
362 }
363
364 /** After deleing a message that is currently visible in a window, 
365  * show the next message from the list, or close the window if there are no more messages.
366  **/
367 void 
368 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
369 {
370         /* Close msg view window or select next */
371         if (!modest_msg_view_window_select_next_message (win) &&
372             !modest_msg_view_window_select_previous_message (win)) {
373                 gboolean ret_value;
374                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
375         }
376 }
377
378
379 void
380 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
381 {
382         TnyList *header_list = NULL;
383         TnyIterator *iter = NULL;
384         TnyHeader *header = NULL;
385         gchar *message = NULL;
386         gchar *desc = NULL;
387         gint response;
388         ModestWindowMgr *mgr;
389         GtkWidget *header_view = NULL;
390
391         g_return_if_fail (MODEST_IS_WINDOW(win));
392         
393         /* Check first if the header view has the focus */
394         if (MODEST_IS_MAIN_WINDOW (win)) {
395                 header_view = 
396                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
397                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
398                 if (!gtk_widget_is_focus (header_view))
399                         return;
400         }
401         
402         /* Get the headers, either from the header view (if win is the main window),
403          * or from the message view window: */
404         header_list = get_selected_headers (win);
405         if (!header_list) return;
406                         
407         /* Check if any of the headers are already opened, or in the process of being opened */
408         if (MODEST_IS_MAIN_WINDOW (win)) {
409                 gint opened_headers = 0;
410
411                 iter = tny_list_create_iterator (header_list);
412                 mgr = modest_runtime_get_window_mgr ();
413                 while (!tny_iterator_is_done (iter)) {
414                         header = TNY_HEADER (tny_iterator_get_current (iter));
415                         if (header) {
416                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
417                                         opened_headers++;
418                                 g_object_unref (header);
419                         }
420                         tny_iterator_next (iter);
421                 }
422                 g_object_unref (iter);
423
424                 if (opened_headers > 0) {
425                         gchar *msg;
426
427                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
428                                                opened_headers);
429
430                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
431                         
432                         g_free (msg);
433                         g_object_unref (header_list);
434                         return;
435                 }
436         }
437
438         /* Select message */
439         if (tny_list_get_length(header_list) == 1) {
440                 iter = tny_list_create_iterator (header_list);
441                 header = TNY_HEADER (tny_iterator_get_current (iter));
442                 if (header) {
443                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
444                         g_object_unref (header);
445                 }
446
447                 g_object_unref (iter);
448         }
449         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
450                                            tny_list_get_length(header_list)), desc);
451
452         /* Confirmation dialog */
453         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
454                                                             message);
455         
456
457         if (response == GTK_RESPONSE_OK) {      
458                 ModestWindow *main_window = NULL;
459                 ModestWindowMgr *mgr = NULL;
460                 GtkTreeModel *model = NULL;
461                 GtkTreeSelection *sel = NULL;
462                 GList *sel_list = NULL, *tmp = NULL;
463                 GtkTreeRowReference *next_row_reference = NULL;
464                 GtkTreeRowReference *prev_row_reference = NULL;
465                 GtkTreePath *next_path = NULL;
466                 GtkTreePath *prev_path = NULL;
467                 ModestMailOperation *mail_op = NULL;
468
469                 /* Find last selected row */                    
470                 if (MODEST_IS_MAIN_WINDOW (win)) {
471                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
472                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
473                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
474                         for (tmp=sel_list; tmp; tmp=tmp->next) {
475                                 if (tmp->next == NULL) {
476                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
477                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
478
479                                         gtk_tree_path_prev (prev_path);
480                                         gtk_tree_path_next (next_path);
481
482                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
483                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
484                                 }
485                         }
486                 }
487                 
488                 /* Disable window dimming management */
489                 modest_window_disable_dimming (MODEST_WINDOW(win));
490
491                 /* Remove each header. If it's a view window header_view == NULL */
492                 mail_op = modest_mail_operation_new ((GObject *) win);
493                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
494                                                  mail_op);
495                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
496                 g_object_unref (mail_op);
497                 
498                 /* Enable window dimming management */
499                 if (sel != NULL) {
500                         gtk_tree_selection_unselect_all (sel);
501                 }
502                 modest_window_enable_dimming (MODEST_WINDOW(win));
503                 
504                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
505                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
506                         
507                         /* Get main window */
508                         mgr = modest_runtime_get_window_mgr ();
509                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
510                 } else {                        
511                         /* Move cursor to next row */
512                         main_window = win; 
513
514                         /* Select next or previous row */
515                         if (gtk_tree_row_reference_valid (next_row_reference)) {
516 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
517                                 gtk_tree_selection_select_path (sel, next_path);
518                         }
519                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
520                                 gtk_tree_selection_select_path (sel, prev_path);
521                         }
522
523                         /* Free */
524                         if (next_row_reference != NULL) 
525                                 gtk_tree_row_reference_free (next_row_reference);
526                         if (next_path != NULL) 
527                                 gtk_tree_path_free (next_path);                         
528                         if (prev_row_reference != NULL) 
529                                 gtk_tree_row_reference_free (prev_row_reference);
530                         if (prev_path != NULL) 
531                                 gtk_tree_path_free (prev_path);                         
532                 }
533                 
534                 /* Update toolbar dimming state */
535                 if (main_window)
536                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
537
538                 /* Free */
539                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
540                 g_list_free (sel_list);
541         }
542
543         /* Free*/
544         g_free(message);
545         g_free(desc);
546         g_object_unref (header_list);
547 }
548
549
550
551
552 /* delete either message or folder, based on where we are */
553 void
554 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
555 {
556         g_return_if_fail (MODEST_IS_WINDOW(win));
557         
558         /* Check first if the header view has the focus */
559         if (MODEST_IS_MAIN_WINDOW (win)) {
560                 GtkWidget *w;
561                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
562                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
563                 if (gtk_widget_is_focus (w)) {
564                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
565                         return;
566                 }
567         }
568         modest_ui_actions_on_delete_message (action, win);
569 }
570
571 void
572 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
573 {       
574         ModestWindowMgr *mgr = NULL;
575         
576 #ifdef MODEST_PLATFORM_MAEMO
577         modest_osso_save_state();
578 #endif /* MODEST_PLATFORM_MAEMO */
579
580         g_debug ("closing down, clearing %d item(s) from operation queue",
581                  modest_mail_operation_queue_num_elements
582                  (modest_runtime_get_mail_operation_queue()));
583
584         /* cancel all outstanding operations */
585         modest_mail_operation_queue_cancel_all 
586                 (modest_runtime_get_mail_operation_queue());
587         
588         g_debug ("queue has been cleared");
589
590
591         /* Check if there are opened editing windows */ 
592         mgr = modest_runtime_get_window_mgr ();
593         modest_window_mgr_close_all_windows (mgr);
594
595         /* note: when modest-tny-account-store is finalized,
596            it will automatically set all network connections
597            to offline */
598
599 /*      gtk_main_quit (); */
600 }
601
602 void
603 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
604 {
605         gboolean ret_value;
606
607         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
608
609 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
610 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
611 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
612 /*              gboolean ret_value; */
613 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
614 /*      } else if (MODEST_IS_WINDOW (win)) { */
615 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
616 /*      } else { */
617 /*              g_return_if_reached (); */
618 /*      } */
619 }
620
621 void
622 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
623 {
624         GtkClipboard *clipboard = NULL;
625         gchar *selection = NULL;
626
627         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
628         selection = gtk_clipboard_wait_for_text (clipboard);
629
630         /* Question: why is the clipboard being used here? 
631          * It doesn't really make a lot of sense. */
632
633         if (selection)
634         {
635                 modest_address_book_add_address (selection);
636                 g_free (selection);
637         }
638 }
639
640 void
641 modest_ui_actions_on_accounts (GtkAction *action, 
642                                ModestWindow *win)
643 {
644         /* This is currently only implemented for Maemo */
645         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
646                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
647                         g_debug ("%s: wizard was already running", __FUNCTION__);
648                 
649                 return;
650         } else {
651                 /* Show the list of accounts */
652                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
653                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
654                 
655                 /* The accounts dialog must be modal */
656                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
657                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
658         }
659 }
660
661 #ifdef MODEST_PLATFORM_MAEMO
662 static void
663 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
664 {
665         /* Save any changes. */
666         modest_connection_specific_smtp_window_save_server_accounts (
667                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
668         gtk_widget_destroy (GTK_WIDGET (window));
669 }
670 #endif
671
672
673 void
674 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
675 {
676         /* This is currently only implemented for Maemo,
677          * because it requires an API (libconic) to detect different connection 
678          * possiblities.
679          */
680 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
681         
682         /* Create the window if necessary: */
683         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
684         modest_connection_specific_smtp_window_fill_with_connections (
685                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
686                 modest_runtime_get_account_mgr());
687
688         /* Show the window: */  
689         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
690         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
691         gtk_widget_show (specific_window);
692     
693         /* Save changes when the window is hidden: */
694         g_signal_connect (specific_window, "hide", 
695                 G_CALLBACK (on_smtp_servers_window_hide), win);
696 #endif /* MODEST_PLATFORM_MAEMO */
697 }
698
699 void
700 modest_ui_actions_compose_msg(ModestWindow *win,
701                               const gchar *to_str,
702                               const gchar *cc_str,
703                               const gchar *bcc_str,
704                               const gchar *subject_str,
705                               const gchar *body_str,
706                               GSList *attachments,
707                               gboolean set_as_modified)
708 {
709         gchar *account_name = NULL;
710         TnyMsg *msg = NULL;
711         TnyAccount *account = NULL;
712         TnyFolder *folder = NULL;
713         gchar *from_str = NULL, *signature = NULL, *body = NULL;
714         gboolean use_signature = FALSE;
715         ModestWindow *msg_win = NULL;
716         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
717         ModestTnyAccountStore *store = modest_runtime_get_account_store();
718
719         account_name = modest_account_mgr_get_default_account(mgr);
720         if (!account_name) {
721                 g_printerr ("modest: no account found\n");
722                 goto cleanup;
723         }
724         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
725         if (!account) {
726                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
727                 goto cleanup;
728         }
729         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
730         if (!folder) {
731                 g_printerr ("modest: failed to find Drafts folder\n");
732                 goto cleanup;
733         }
734         from_str = modest_account_mgr_get_from_string (mgr, account_name);
735         if (!from_str) {
736                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
737                 goto cleanup;
738         }
739
740         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
741         if (body_str != NULL) {
742                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
743         } else {
744                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
745         }
746
747         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
748         if (!msg) {
749                 g_printerr ("modest: failed to create new msg\n");
750                 goto cleanup;
751         }
752
753         /* Create and register edit window */
754         /* This is destroyed by TODO. */
755         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
756         while (attachments) {
757                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
758                                                        attachments->data);
759                 attachments = g_slist_next(attachments);
760         }
761         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
762         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
763
764         gtk_widget_show_all (GTK_WIDGET (msg_win));
765
766 cleanup:
767         g_free (from_str);
768         g_free (signature);
769         g_free (body);
770         g_free (account_name);
771         if (account) g_object_unref (G_OBJECT(account));
772         if (folder) g_object_unref (G_OBJECT(folder));
773         if (msg_win) g_object_unref (G_OBJECT(msg_win));
774         if (msg) g_object_unref (G_OBJECT(msg));
775 }
776
777 void
778 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
779 {
780         /* if there are no accounts yet, just show the wizard */
781         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
782                 if (!modest_ui_actions_run_account_setup_wizard (win))
783                         return;
784                 
785         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
786 }
787
788
789 gboolean 
790 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
791                                        TnyHeader *header,
792                                        TnyMsg *msg)
793 {
794         ModestMailOperationStatus status;
795
796         /* If there is no message or the operation was not successful */
797         status = modest_mail_operation_get_status (mail_op);
798         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
799
800                 /* Remove the header from the preregistered uids */
801                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
802                                                      header);
803
804                 return FALSE;
805         }
806
807         return TRUE;
808 }
809
810 typedef struct {
811         guint idle_handler;
812         gchar *message;
813         GtkWidget *banner;
814 } OpenMsgBannerInfo;
815
816 gboolean
817 open_msg_banner_idle (gpointer userdata)
818 {
819         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
820
821         gdk_threads_enter ();
822         banner_info->idle_handler = 0;
823         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
824         g_object_ref (banner_info->banner);
825         
826         gdk_threads_leave ();
827
828         return FALSE;
829         
830 }
831
832 static void
833 open_msg_cb (ModestMailOperation *mail_op, 
834              TnyHeader *header,  
835              gboolean canceled,
836              TnyMsg *msg, 
837              GError *err,
838              gpointer user_data)
839 {
840         ModestWindowMgr *mgr = NULL;
841         ModestWindow *parent_win = NULL;
842         ModestWindow *win = NULL;
843         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
844         gchar *account = NULL;
845         TnyFolder *folder;
846         gboolean open_in_editor = FALSE;
847         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) user_data;
848         
849         /* Do nothing if there was any problem with the mail
850            operation. The error will be shown by the error_handler of
851            the mail operation */
852         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
853                 goto banner_cleanup;
854
855         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
856         folder = tny_header_get_folder (header);
857
858         /* Mark header as read */
859         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
860
861         /* Gets folder type (OUTBOX headers will be opened in edit window */
862         if (modest_tny_folder_is_local_folder (folder)) {
863                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
864                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
865                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
866         }
867
868                 
869         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
870                 TnyTransportAccount *traccount = NULL;
871                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
872                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
873                 if (traccount) {
874                         ModestTnySendQueue *send_queue = NULL;
875                         ModestTnySendQueueStatus status;
876                         char *msg_id;
877                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
878                                                    TNY_ACCOUNT(traccount)));
879                         send_queue = modest_runtime_get_send_queue(traccount);
880                         msg_id = modest_tny_send_queue_get_msg_id (header);
881                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
882                         /* Only open messages in outbox with the editor if they are in Failed state */
883                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
884                                 open_in_editor = TRUE;
885                         }
886                         g_free(msg_id);
887                         g_object_unref(traccount);
888                 } else {
889                         g_warning("Cannot get transport account for message in outbox!!");
890                 }
891         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
892                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
893         }
894
895         /* Get account */
896         if (!account)
897                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
898         if (!account)
899                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
900         
901         if (open_in_editor) {
902                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
903                 const gchar *from_header = NULL;
904
905                 from_header = tny_header_get_from (header);
906
907                 /* we cannot edit without a valid account... */
908                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
909                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
910                                 goto cleanup;
911                 }
912                 
913                 if (from_header) {
914                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
915                         GSList *node = NULL;
916                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
917                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
918                                 
919                                 if (from && (strcmp (from_header, from) == 0)) {
920                                         g_free (account);
921                                         account = g_strdup (node->data);
922                                         g_free (from);
923                                         break;
924                                 }
925                                 g_free (from);
926                         }
927                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
928                         g_slist_free (accounts);
929                 }
930
931                 win = modest_msg_edit_window_new (msg, account, TRUE);
932
933
934
935         } else {
936                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
937                 
938                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
939                         GtkWidget *header_view;
940                         GtkTreeSelection *sel;
941                         GList *sel_list = NULL;
942                         GtkTreeModel *model;
943                         
944                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
945                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
946
947                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
948                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
949
950                         if (sel_list != NULL) {
951                                 GtkTreeRowReference *row_reference;
952
953                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
954                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
955                                 g_list_free (sel_list);
956                                 
957                                 win = modest_msg_view_window_new_with_header_model (
958                                                 msg, account, (const gchar*) uid,
959                                                 model, row_reference);
960                                 gtk_tree_row_reference_free (row_reference);
961                         } else {
962                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
963                         }
964                 } else {
965                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
966                 }
967                 g_free (uid);
968         }
969         
970         /* Register and show new window */
971         if (win != NULL) {
972                 mgr = modest_runtime_get_window_mgr ();
973                 modest_window_mgr_register_window (mgr, win);
974                 g_object_unref (win);
975                 gtk_widget_show_all (GTK_WIDGET(win));
976         }
977
978         /* Update toolbar dimming state */
979         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
980                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
981         }
982
983 cleanup:
984         /* Free */
985         g_free(account);
986         g_object_unref (parent_win);
987         g_object_unref (folder);
988 banner_cleanup:
989         if (banner_info) {
990                 g_free (banner_info->message);
991                 if (banner_info->idle_handler > 0) {
992                         g_source_remove (banner_info->idle_handler);
993                         banner_info->idle_handler = 0;
994                 }
995                 if (banner_info->banner != NULL) {
996                         gtk_widget_destroy (banner_info->banner);
997                         g_object_unref (banner_info->banner);
998                         banner_info->banner = NULL;
999                 }
1000                 g_slice_free (OpenMsgBannerInfo, banner_info);
1001         }
1002 }
1003
1004 void
1005 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1006                                                gpointer user_data)
1007 {
1008         const GError *error;
1009         GObject *win = NULL;
1010
1011         win = modest_mail_operation_get_source (mail_op);
1012         error = modest_mail_operation_get_error (mail_op);
1013
1014         /* Show error */
1015         if (error->code == TNY_SYSTEM_ERROR_MEMORY ||
1016             error->code == TNY_IO_ERROR_WRITE ||
1017             error->code == TNY_IO_ERROR_READ) {
1018                 ModestMailOperationStatus st = modest_mail_operation_get_status (mail_op);
1019                 /* If the mail op has been cancelled then it's not an error: don't show any message */
1020                 if (st != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1021                         modest_platform_information_banner ((GtkWidget *) win,
1022                                                             NULL, dgettext("ke-recv",
1023                                                                            "cerm_device_memory_full"));
1024                 }
1025         } else if (user_data) {
1026                 modest_platform_information_banner ((GtkWidget *) win, 
1027                                                     NULL, user_data);
1028         }
1029
1030         if (win)
1031                 g_object_unref (win);
1032 }
1033
1034 /**
1035  * Returns the account a list of headers belongs to. It returns a
1036  * *new* reference so don't forget to unref it
1037  */
1038 static TnyAccount*
1039 get_account_from_header_list (TnyList *headers)
1040 {
1041         TnyAccount *account = NULL;
1042
1043         if (tny_list_get_length (headers) > 0) {
1044                 TnyIterator *iter = tny_list_create_iterator (headers);
1045                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1046                 TnyFolder *folder = tny_header_get_folder (header);
1047                 
1048                 if (!folder) {
1049                         g_object_unref (header);
1050                         
1051                         while (!tny_iterator_is_done (iter)) {
1052                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1053                                 folder = tny_header_get_folder (header);
1054                                 if (folder) 
1055                                         break;
1056                                 g_object_unref (header);
1057                                 header = NULL;
1058                                 tny_iterator_next (iter);
1059                         }
1060                 }
1061
1062                 if (folder) {
1063                         account = tny_folder_get_account (folder);
1064                         g_object_unref (folder);
1065                 }
1066                 
1067                 if (header)
1068                         g_object_unref (header);
1069                 
1070                 g_object_unref (iter);
1071         }
1072         return account;
1073 }
1074
1075 static void 
1076 foreach_unregister_headers (gpointer data,
1077                             gpointer user_data)
1078 {
1079         ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1080         TnyHeader *header = TNY_HEADER (data);
1081
1082         modest_window_mgr_unregister_header (mgr, header);
1083 }
1084
1085 static void
1086 open_msgs_performer(gboolean canceled, 
1087                     GError *err,
1088                     GtkWindow *parent_window,
1089                     TnyAccount *account,
1090                     gpointer user_data)
1091 {
1092         ModestMailOperation *mail_op = NULL;
1093         const gchar *proto_name;
1094         gchar *error_msg;
1095         ModestTransportStoreProtocol proto;
1096         TnyList *not_opened_headers;
1097         TnyConnectionStatus status;
1098         gboolean show_open_draft = FALSE;
1099         OpenMsgBannerInfo *banner_info = NULL;
1100
1101         not_opened_headers = TNY_LIST (user_data);
1102
1103         status = tny_account_get_connection_status (account);
1104         if (err || canceled) {
1105                 /* Unregister the already registered headers */
1106                 tny_list_foreach (not_opened_headers, foreach_unregister_headers, 
1107                                   modest_runtime_get_window_mgr ());
1108                 goto clean;
1109         }
1110
1111         /* Get the error message depending on the protocol */
1112         proto_name = tny_account_get_proto (account);
1113         if (proto_name != NULL) {
1114                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1115         } else {
1116                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1117         }
1118         
1119         /* Create the error messages */
1120         if (tny_list_get_length (not_opened_headers) == 1) {
1121                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1122                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1123                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1124                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1125                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1126                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1127                                                      tny_header_get_subject (header));
1128                         g_object_unref (header);
1129                         g_object_unref (iter);
1130                 } else {
1131                         TnyHeader *header;
1132                         TnyFolder *folder;
1133                         TnyIterator *iter;
1134                         TnyFolderType folder_type;
1135
1136                         iter = tny_list_create_iterator (not_opened_headers);
1137                         header = TNY_HEADER (tny_iterator_get_current (iter));
1138                         folder = tny_header_get_folder (header);
1139                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1140                         show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1141                         g_object_unref (folder);
1142                         g_object_unref (header);
1143                         g_object_unref (iter);
1144                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1145                 }
1146         } else {
1147                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1148         }
1149
1150         /* Create the mail operation */
1151         mail_op = 
1152                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1153                                                                modest_ui_actions_get_msgs_full_error_handler,
1154                                                                error_msg, g_free);
1155         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1156                                          mail_op);
1157
1158         if (show_open_draft) {
1159                 banner_info = g_slice_new (OpenMsgBannerInfo);
1160                 banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1161                 banner_info->banner = NULL;
1162                 banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle, banner_info);
1163         }
1164
1165         modest_mail_operation_get_msgs_full (mail_op,
1166                                              not_opened_headers,
1167                                              open_msg_cb,
1168                                              banner_info,
1169                                              NULL);
1170
1171         /* Frees */
1172  clean:
1173         if (mail_op)
1174                 g_object_unref (mail_op);
1175         g_object_unref (not_opened_headers);
1176         g_object_unref (account);
1177 }
1178
1179 /*
1180  * This function is used by both modest_ui_actions_on_open and
1181  * modest_ui_actions_on_header_activated. This way we always do the
1182  * same when trying to open messages.
1183  */
1184 static void
1185 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1186 {
1187         ModestWindowMgr *mgr = NULL;
1188         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1189         TnyList *not_opened_headers = NULL;
1190         TnyHeaderFlags flags = 0;
1191         TnyAccount *account;
1192         gint uncached_msgs = 0;
1193                 
1194         g_return_if_fail (headers != NULL);
1195
1196         /* Check that only one message is selected for opening */
1197         if (tny_list_get_length (headers) != 1) {
1198                 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1199                                                     NULL, _("mcen_ib_select_one_message"));
1200                 return;
1201         }
1202
1203         mgr = modest_runtime_get_window_mgr ();
1204         iter = tny_list_create_iterator (headers);
1205
1206         /* Get the account */
1207         account = get_account_from_header_list (headers);
1208         
1209         /* Look if we already have a message view for each header. If
1210            true, then remove the header from the list of headers to
1211            open */
1212         not_opened_headers = tny_simple_list_new ();
1213         while (!tny_iterator_is_done (iter)) {
1214
1215                 ModestWindow *window = NULL;
1216                 TnyHeader *header = NULL;
1217                 gboolean found = FALSE;
1218                 
1219                 header = TNY_HEADER (tny_iterator_get_current (iter));
1220                 if (header)
1221                         flags = tny_header_get_flags (header);
1222
1223                 window = NULL;
1224                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1225                 
1226                 /* Do not open again the message and present the
1227                    window to the user */
1228                 if (found) {
1229                         if (window)
1230                                 gtk_window_present (GTK_WINDOW (window));
1231                         else
1232                                 /* the header has been registered already, we don't do
1233                                  * anything but wait for the window to come up*/
1234                                 g_debug ("header %p already registered, waiting for window", header);
1235                 } else {
1236                         tny_list_append (not_opened_headers, G_OBJECT (header));
1237                 }
1238
1239                 if (header)
1240                         g_object_unref (header);
1241
1242                 tny_iterator_next (iter);
1243         }
1244         g_object_unref (iter);
1245         iter = NULL;
1246
1247         /* Open each message */
1248         if (tny_list_get_length (not_opened_headers) == 0)
1249                 goto cleanup;
1250         
1251         /* If some messages would have to be downloaded, ask the user to 
1252          * make a connection. It's generally easier to do this here (in the mainloop) 
1253          * than later in a thread:
1254          */
1255         if (tny_list_get_length (not_opened_headers) > 0) {
1256                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1257
1258                 if (uncached_msgs > 0) {
1259                         /* Allways download if we are online. */
1260                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1261                                 gint response;
1262
1263                                 /* If ask for user permission to download the messages */
1264                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1265                                                                                     ngettext("mcen_nc_get_msg",
1266                                                                                              "mcen_nc_get_msgs",
1267                                                                                              uncached_msgs));
1268
1269                                 /* End if the user does not want to continue */
1270                                 if (response == GTK_RESPONSE_CANCEL)
1271                                         goto cleanup;
1272                         }
1273                 }
1274         }
1275         
1276         /* Register the headers before actually creating the windows: */
1277         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1278         while (!tny_iterator_is_done (iter_not_opened)) {
1279                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1280                 if (header) {
1281                         modest_window_mgr_register_header (mgr, header, NULL);
1282                         g_object_unref (header);
1283                 }
1284                 tny_iterator_next (iter_not_opened);
1285         }
1286         g_object_unref (iter_not_opened);
1287         iter_not_opened = NULL;
1288
1289         /* Connect to the account and perform */
1290         if (uncached_msgs > 0) {
1291                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account), 
1292                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1293         } else {
1294                 /* Call directly the performer, do not need to connect */
1295                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1296                                      g_object_ref (not_opened_headers));
1297         }
1298 cleanup:
1299         /* Clean */
1300         if (account)
1301                 g_object_unref (account);
1302         if (not_opened_headers)
1303                 g_object_unref (not_opened_headers);
1304 }
1305
1306 void
1307 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1308 {
1309         TnyList *headers;
1310
1311         /* Get headers */
1312         headers = get_selected_headers (win);
1313         if (!headers)
1314                 return;
1315
1316         /* Open them */
1317         open_msgs_from_headers (headers, win);
1318
1319         g_object_unref(headers);
1320 }
1321
1322
1323 static void
1324 free_reply_forward_helper (gpointer data)
1325 {
1326         ReplyForwardHelper *helper;
1327
1328         helper = (ReplyForwardHelper *) data;
1329         g_free (helper->account_name);
1330         g_slice_free (ReplyForwardHelper, helper);
1331 }
1332
1333 static void
1334 reply_forward_cb (ModestMailOperation *mail_op,  
1335                   TnyHeader *header, 
1336                   gboolean canceled,
1337                   TnyMsg *msg,
1338                   GError *err,
1339                   gpointer user_data)
1340 {
1341         TnyMsg *new_msg;
1342         ReplyForwardHelper *rf_helper;
1343         ModestWindow *msg_win = NULL;
1344         ModestEditType edit_type;
1345         gchar *from = NULL;
1346         TnyAccount *account = NULL;
1347         ModestWindowMgr *mgr = NULL;
1348         gchar *signature = NULL;
1349         gboolean use_signature;
1350
1351         /* If there was any error. The mail operation could be NULL,
1352            this means that we already have the message downloaded and
1353            that we didn't do a mail operation to retrieve it */
1354         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1355                 return;
1356                         
1357         g_return_if_fail (user_data != NULL);
1358         rf_helper = (ReplyForwardHelper *) user_data;
1359
1360         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1361                                                    rf_helper->account_name);
1362         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1363                                                       rf_helper->account_name, 
1364                                                       &use_signature);
1365
1366         /* Create reply mail */
1367         switch (rf_helper->action) {
1368         case ACTION_REPLY:
1369                 new_msg = 
1370                         modest_tny_msg_create_reply_msg (msg, header, from, 
1371                                                          (use_signature) ? signature : NULL,
1372                                                          rf_helper->reply_forward_type,
1373                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1374                 break;
1375         case ACTION_REPLY_TO_ALL:
1376                 new_msg = 
1377                         modest_tny_msg_create_reply_msg (msg, header, from, 
1378                                                          (use_signature) ? signature : NULL, 
1379                                                          rf_helper->reply_forward_type,
1380                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1381                 edit_type = MODEST_EDIT_TYPE_REPLY;
1382                 break;
1383         case ACTION_FORWARD:
1384                 new_msg = 
1385                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL, 
1386                                                            rf_helper->reply_forward_type);
1387                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1388                 break;
1389         default:
1390                 g_return_if_reached ();
1391                 return;
1392         }
1393
1394         g_free (signature);
1395
1396         if (!new_msg) {
1397                 g_printerr ("modest: failed to create message\n");
1398                 goto cleanup;
1399         }
1400
1401         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1402                                                                        rf_helper->account_name,
1403                                                                        TNY_ACCOUNT_TYPE_STORE);
1404         if (!account) {
1405                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1406                 goto cleanup;
1407         }
1408
1409         /* Create and register the windows */
1410         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1411         mgr = modest_runtime_get_window_mgr ();
1412         modest_window_mgr_register_window (mgr, msg_win);
1413
1414         if (rf_helper->parent_window != NULL) {
1415                 gdouble parent_zoom;
1416
1417                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1418                 modest_window_set_zoom (msg_win, parent_zoom);
1419         }
1420
1421         /* Show edit window */
1422         gtk_widget_show_all (GTK_WIDGET (msg_win));
1423
1424 cleanup:
1425         if (msg_win)
1426                 g_object_unref (msg_win);
1427         if (new_msg)
1428                 g_object_unref (G_OBJECT (new_msg));
1429         if (account)
1430                 g_object_unref (G_OBJECT (account));
1431 /*      g_object_unref (msg); */
1432         free_reply_forward_helper (rf_helper);
1433 }
1434
1435 /* Checks a list of headers. If any of them are not currently
1436  * downloaded (CACHED) then returns TRUE else returns FALSE.
1437  */
1438 static gint
1439 header_list_count_uncached_msgs (TnyList *header_list)
1440 {
1441         TnyIterator *iter;
1442         gint uncached_messages = 0;
1443
1444         iter = tny_list_create_iterator (header_list);
1445         while (!tny_iterator_is_done (iter)) {
1446                 TnyHeader *header;
1447
1448                 header = TNY_HEADER (tny_iterator_get_current (iter));
1449                 if (header) {
1450                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1451                                 uncached_messages ++;
1452                         g_object_unref (header);
1453                 }
1454
1455                 tny_iterator_next (iter);
1456         }
1457         g_object_unref (iter);
1458
1459         return uncached_messages;
1460 }
1461
1462 /* Returns FALSE if the user does not want to download the
1463  * messages. Returns TRUE if the user allowed the download.
1464  */
1465 static gboolean
1466 connect_to_get_msg (ModestWindow *win,
1467                     gint num_of_uncached_msgs,
1468                     TnyAccount *account)
1469 {
1470         GtkResponseType response;
1471
1472         /* Allways download if we are online. */
1473         if (tny_device_is_online (modest_runtime_get_device ()))
1474                 return TRUE;
1475
1476         /* If offline, then ask for user permission to download the messages */
1477         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1478                         ngettext("mcen_nc_get_msg",
1479                         "mcen_nc_get_msgs",
1480                         num_of_uncached_msgs));
1481
1482         if (response == GTK_RESPONSE_CANCEL)
1483                 return FALSE;
1484
1485         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1486 }
1487
1488 /*
1489  * Common code for the reply and forward actions
1490  */
1491 static void
1492 reply_forward (ReplyForwardAction action, ModestWindow *win)
1493 {
1494         ModestMailOperation *mail_op = NULL;
1495         TnyList *header_list = NULL;
1496         ReplyForwardHelper *rf_helper = NULL;
1497         guint reply_forward_type;
1498         gboolean continue_download = TRUE;
1499         gboolean do_retrieve = TRUE;
1500         
1501         g_return_if_fail (MODEST_IS_WINDOW(win));
1502
1503         /* we need an account when editing */
1504         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1505                 if (!modest_ui_actions_run_account_setup_wizard (win))
1506                         return;
1507         }
1508         
1509         header_list = get_selected_headers (win);
1510         if (!header_list)
1511                 return;
1512
1513         reply_forward_type = 
1514                 modest_conf_get_int (modest_runtime_get_conf (),
1515                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1516                                      NULL);
1517
1518         /* check if we need to download msg before asking about it */
1519         do_retrieve = (action == ACTION_FORWARD) ||
1520                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1521
1522         if (do_retrieve){
1523                 gint num_of_unc_msgs;
1524
1525                 /* check that the messages have been previously downloaded */
1526                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1527                 /* If there are any uncached message ask the user
1528                  * whether he/she wants to download them. */
1529                 if (num_of_unc_msgs) {
1530                         TnyAccount *account = get_account_from_header_list (header_list);
1531                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1532                         g_object_unref (account);
1533                 }
1534         }
1535
1536         if (!continue_download) {
1537                 g_object_unref (header_list);
1538                 return;
1539         }
1540         
1541         /* We assume that we can only select messages of the
1542            same folder and that we reply all of them from the
1543            same account. In fact the interface currently only
1544            allows single selection */
1545         
1546         /* Fill helpers */
1547         rf_helper = g_slice_new0 (ReplyForwardHelper);
1548         rf_helper->reply_forward_type = reply_forward_type;
1549         rf_helper->action = action;
1550         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1551         
1552         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1553                 rf_helper->parent_window = GTK_WIDGET (win);
1554         if (!rf_helper->account_name)
1555                 rf_helper->account_name =
1556                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1557
1558         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1559                 TnyMsg *msg;
1560                 TnyHeader *header;
1561                 /* Get header and message. Do not free them here, the
1562                    reply_forward_cb must do it */
1563                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1564                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1565                 if (!msg || !header) {
1566                         if (msg)
1567                                 g_object_unref (msg);
1568                         g_printerr ("modest: no message found\n");
1569                         return;
1570                 } else {
1571                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1572                 }
1573                 if (header)
1574                         g_object_unref (header);
1575         } else {
1576                 TnyHeader *header;
1577                 TnyIterator *iter;
1578
1579                 /* Only reply/forward to one message */
1580                 iter = tny_list_create_iterator (header_list);
1581                 header = TNY_HEADER (tny_iterator_get_current (iter));
1582                 g_object_unref (iter);
1583
1584                 if (header) {
1585                         /* Retrieve messages */
1586                         if (do_retrieve) {
1587                                 mail_op = 
1588                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1589                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1590                                                                                        NULL, NULL);
1591                                 modest_mail_operation_queue_add (
1592                                         modest_runtime_get_mail_operation_queue (), mail_op);
1593                                 
1594                                 modest_mail_operation_get_msg (mail_op,
1595                                                                header,
1596                                                                reply_forward_cb,
1597                                                                rf_helper);
1598                                 /* Clean */
1599                                 g_object_unref(mail_op);
1600                         } else {
1601                                 /* we put a ref here to prevent double unref as the reply
1602                                  * forward callback unrefs the header at its end */
1603                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1604                         }
1605
1606
1607                         g_object_unref (header);
1608                 }
1609
1610         }
1611
1612         /* Free */
1613         g_object_unref (header_list);
1614 }
1615
1616 void
1617 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1618 {
1619         g_return_if_fail (MODEST_IS_WINDOW(win));
1620
1621         reply_forward (ACTION_REPLY, win);
1622 }
1623
1624 void
1625 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1626 {
1627         g_return_if_fail (MODEST_IS_WINDOW(win));
1628
1629         reply_forward (ACTION_FORWARD, win);
1630 }
1631
1632 void
1633 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1634 {
1635         g_return_if_fail (MODEST_IS_WINDOW(win));
1636
1637         reply_forward (ACTION_REPLY_TO_ALL, win);
1638 }
1639
1640 void 
1641 modest_ui_actions_on_next (GtkAction *action, 
1642                            ModestWindow *window)
1643 {
1644         if (MODEST_IS_MAIN_WINDOW (window)) {
1645                 GtkWidget *header_view;
1646
1647                 header_view = modest_main_window_get_child_widget (
1648                                 MODEST_MAIN_WINDOW(window),
1649                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1650                 if (!header_view)
1651                         return;
1652         
1653                 modest_header_view_select_next (
1654                                 MODEST_HEADER_VIEW(header_view)); 
1655         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1656                 modest_msg_view_window_select_next_message (
1657                                 MODEST_MSG_VIEW_WINDOW (window));
1658         } else {
1659                 g_return_if_reached ();
1660         }
1661 }
1662
1663 void 
1664 modest_ui_actions_on_prev (GtkAction *action, 
1665                            ModestWindow *window)
1666 {
1667         g_return_if_fail (MODEST_IS_WINDOW(window));
1668
1669         if (MODEST_IS_MAIN_WINDOW (window)) {
1670                 GtkWidget *header_view;
1671                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1672                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1673                 if (!header_view)
1674                         return;
1675                 
1676                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1677         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1678                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1679         } else {
1680                 g_return_if_reached ();
1681         }
1682 }
1683
1684 void 
1685 modest_ui_actions_on_sort (GtkAction *action, 
1686                            ModestWindow *window)
1687 {
1688         g_return_if_fail (MODEST_IS_WINDOW(window));
1689
1690         if (MODEST_IS_MAIN_WINDOW (window)) {
1691                 GtkWidget *header_view;
1692                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1693                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1694                 if (!header_view) {
1695                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1696
1697                         return;
1698                 }
1699
1700                 /* Show sorting dialog */
1701                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1702         }
1703 }
1704
1705 static void
1706 new_messages_arrived (ModestMailOperation *self, 
1707                       TnyList *new_headers,
1708                       gpointer user_data)
1709 {
1710         GObject *source;
1711         gboolean show_visual_notifications;
1712
1713         source = modest_mail_operation_get_source (self);
1714         show_visual_notifications = (source) ? FALSE : TRUE;
1715         if (source)
1716                 g_object_unref (source);
1717
1718         /* Notify new messages have been downloaded. If the
1719            send&receive was invoked by the user then do not show any
1720            visual notification, only play a sound and activate the LED
1721            (for the Maemo version) */
1722         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1723                 modest_platform_on_new_headers_received (new_headers, 
1724                                                          show_visual_notifications);
1725
1726 }
1727
1728 gboolean
1729 retrieve_all_messages_cb (GObject *source,
1730                           guint num_msgs,
1731                           guint retrieve_limit)
1732 {
1733         GtkWindow *window;
1734         gchar *msg;
1735         gint response;
1736
1737         window = GTK_WINDOW (source);
1738         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1739                                num_msgs, retrieve_limit);
1740
1741         /* Ask the user if they want to retrieve all the messages */
1742         response = 
1743                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1744                                                                       _("mcen_bd_get_all"),
1745                                                                       _("mcen_bd_newest_only"));
1746         /* Free and return */
1747         g_free (msg);
1748         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1749 }
1750
1751 typedef struct {
1752         TnyAccount *account;
1753         ModestWindow *win;
1754         gchar *account_name;
1755         gboolean poke_status;
1756 } SendReceiveInfo;
1757
1758 static void
1759 do_send_receive_performer (gboolean canceled, 
1760                            GError *err,
1761                            GtkWindow *parent_window, 
1762                            TnyAccount *account, 
1763                            gpointer user_data)
1764 {
1765         ModestMailOperation *mail_op;
1766         SendReceiveInfo *info;
1767
1768         info = (SendReceiveInfo *) user_data;
1769
1770         if (err || canceled) {
1771                 goto clean;
1772         }
1773
1774         /* Set send/receive operation in progress */    
1775         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1776                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1777         }
1778         
1779         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1780                                                                  modest_ui_actions_send_receive_error_handler,
1781                                                                  NULL, NULL);
1782
1783         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1784                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1785                                   G_CALLBACK (on_send_receive_finished), 
1786                                   info->win);
1787
1788         /* Send & receive. */
1789         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1790         modest_mail_operation_update_account (mail_op, info->account_name, info->poke_status,
1791                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1792                                               new_messages_arrived, info->win);
1793         g_object_unref (G_OBJECT (mail_op));
1794         
1795  clean:
1796         /* Frees */
1797         if (info->account_name)
1798                 g_free (info->account_name);
1799         if (info->win)
1800                 g_object_unref (info->win);
1801         if (info->account)
1802                 g_object_unref (info->account);
1803         g_slice_free (SendReceiveInfo, info);
1804 }
1805
1806 /*
1807  * This function performs the send & receive required actions. The
1808  * window is used to create the mail operation. Typically it should
1809  * always be the main window, but we pass it as argument in order to
1810  * be more flexible.
1811  */
1812 void
1813 modest_ui_actions_do_send_receive (const gchar *account_name, 
1814                                    gboolean force_connection,
1815                                    gboolean poke_status,
1816                                    ModestWindow *win)
1817 {
1818         gchar *acc_name = NULL;
1819         SendReceiveInfo *info;
1820         ModestTnyAccountStore *acc_store;
1821
1822         /* If no account name was provided then get the current account, and if
1823            there is no current account then pick the default one: */
1824         if (!account_name) {
1825                 if (win)
1826                         acc_name = g_strdup (modest_window_get_active_account (win));
1827                 if (!acc_name)
1828                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1829                 if (!acc_name) {
1830                         g_printerr ("modest: cannot get default account\n");
1831                         return;
1832                 }
1833         } else {
1834                 acc_name = g_strdup (account_name);
1835         }
1836
1837         acc_store = modest_runtime_get_account_store ();
1838
1839         /* Create the info for the connect and perform */
1840         info = g_slice_new (SendReceiveInfo);
1841         info->account_name = acc_name;
1842         info->win = (win) ? g_object_ref (win) : NULL;
1843         info->poke_status = poke_status;
1844         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1845                                                                      TNY_ACCOUNT_TYPE_STORE);
1846
1847         /* Invoke the connect and perform */
1848         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
1849                                              force_connection, info->account, 
1850                                              do_send_receive_performer, info);
1851 }
1852
1853
1854 static void
1855 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1856                                   ModestWindow *win)
1857 {
1858         TnyTransportAccount *transport_account;
1859         TnySendQueue *send_queue = NULL;
1860         GError *error = NULL;
1861
1862         /* Get transport account */
1863         transport_account =
1864                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1865                                       (modest_runtime_get_account_store(),
1866                                        account_name,
1867                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1868         if (!transport_account) {
1869                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1870                 goto frees;
1871         }
1872
1873         /* Get send queue*/
1874         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1875         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1876                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1877                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1878                              "modest: could not find send queue for account\n");
1879         } else {
1880                 /* Cancel the current send */
1881                 tny_account_cancel (TNY_ACCOUNT (transport_account));
1882
1883                 /* Suspend all pending messages */
1884                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
1885         }
1886
1887  frees:
1888         if (transport_account != NULL) 
1889                 g_object_unref (G_OBJECT (transport_account));
1890 }
1891
1892 static void
1893 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1894 {
1895         GSList *account_names, *iter;
1896
1897         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1898                                                           TRUE);
1899
1900         iter = account_names;
1901         while (iter) {                  
1902                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1903                 iter = g_slist_next (iter);
1904         }
1905
1906         modest_account_mgr_free_account_names (account_names);
1907         account_names = NULL;
1908 }
1909
1910 void
1911 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1912
1913 {
1914         /* Check if accounts exist */
1915         gboolean accounts_exist = 
1916                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1917         
1918         /* If not, allow the user to create an account before trying to send/receive. */
1919         if (!accounts_exist)
1920                 modest_ui_actions_on_accounts (NULL, win);
1921         
1922         /* Cancel all sending operaitons */     
1923         modest_ui_actions_cancel_send_all (win);
1924 }
1925
1926 /*
1927  * Refreshes all accounts. This function will be used by automatic
1928  * updates
1929  */
1930 void
1931 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
1932                                        gboolean force_connection,
1933                                        gboolean poke_status)
1934 {
1935         GSList *account_names, *iter;
1936
1937         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1938                                                           TRUE);
1939
1940         iter = account_names;
1941         while (iter) {                  
1942                 modest_ui_actions_do_send_receive ((const char*) iter->data, 
1943                                                    force_connection, 
1944                                                    poke_status, win);
1945                 iter = g_slist_next (iter);
1946         }
1947
1948         modest_account_mgr_free_account_names (account_names);
1949         account_names = NULL;
1950 }
1951
1952 /*
1953  * Handler of the click on Send&Receive button in the main toolbar
1954  */
1955 void
1956 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1957 {
1958         /* Check if accounts exist */
1959         gboolean accounts_exist;
1960
1961         accounts_exist =
1962                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1963         
1964         /* If not, allow the user to create an account before trying to send/receive. */
1965         if (!accounts_exist)
1966                 modest_ui_actions_on_accounts (NULL, win);
1967         
1968         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1969         if (MODEST_IS_MAIN_WINDOW (win)) {
1970                 GtkWidget *folder_view;
1971                 TnyFolderStore *folder_store;
1972
1973                 folder_view = 
1974                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1975                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1976                 if (!folder_view)
1977                         return;
1978                 
1979                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1980         
1981                 if (folder_store)
1982                         g_object_unref (folder_store);
1983         }       
1984         
1985         /* Refresh the active account. Force the connection if needed
1986            and poke the status of all folders */
1987         modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, win);
1988 }
1989
1990
1991 void
1992 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1993 {
1994         ModestConf *conf;
1995         GtkWidget *header_view;
1996         
1997         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1998
1999         header_view = modest_main_window_get_child_widget (main_window,
2000                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2001         if (!header_view)
2002                 return;
2003
2004         conf = modest_runtime_get_conf ();
2005         
2006         /* what is saved/restored is depending on the style; thus; we save with
2007          * old style, then update the style, and restore for this new style
2008          */
2009         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2010         
2011         if (modest_header_view_get_style
2012             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2013                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2014                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2015         else
2016                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2017                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2018
2019         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2020                                       MODEST_CONF_HEADER_VIEW_KEY);
2021 }
2022
2023
2024 void 
2025 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
2026                                       TnyHeader *header,
2027                                       ModestMainWindow *main_window)
2028 {
2029         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2030         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2031         
2032         /* in the case the folder is empty, show the empty folder message and focus
2033          * folder view */
2034         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2035                 if (modest_header_view_is_empty (header_view)) {
2036                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2037                         GtkWidget *folder_view = 
2038                                 modest_main_window_get_child_widget (main_window,
2039                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2040                         if (folder != NULL) 
2041                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2042                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2043                         return;
2044                 }
2045         }
2046         /* If no header has been selected then exit */
2047         if (!header)
2048                 return;
2049
2050         /* Update focus */
2051         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2052             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2053
2054         /* Update toolbar dimming state */
2055         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2056         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2057 }
2058
2059 void
2060 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2061                                        TnyHeader *header,
2062                                        ModestMainWindow *main_window)
2063 {
2064         TnyList *headers;
2065
2066         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2067
2068         if (!header)
2069                 return;
2070
2071         if (modest_header_view_count_selected_headers (header_view) > 1) {
2072                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2073                 return;
2074         }
2075
2076
2077 /*      headers = tny_simple_list_new (); */
2078 /*      tny_list_prepend (headers, G_OBJECT (header)); */
2079         headers = modest_header_view_get_selected_headers (header_view);
2080
2081         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2082
2083         g_object_unref (headers);
2084 }
2085
2086 static void
2087 set_active_account_from_tny_account (TnyAccount *account,
2088                                      ModestWindow *window)
2089 {
2090         const gchar *server_acc_name = tny_account_get_id (account);
2091         
2092         /* We need the TnyAccount provided by the
2093            account store because that is the one that
2094            knows the name of the Modest account */
2095         TnyAccount *modest_server_account = modest_server_account = 
2096                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2097                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2098                                                              server_acc_name);
2099         if (!modest_server_account) {
2100                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2101                 return;
2102         }
2103
2104         /* Update active account, but only if it's not a pseudo-account */
2105         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2106             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2107                 const gchar *modest_acc_name = 
2108                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2109                 if (modest_acc_name)
2110                         modest_window_set_active_account (window, modest_acc_name);
2111         }
2112         
2113         g_object_unref (modest_server_account);
2114 }
2115
2116
2117 static void
2118 folder_refreshed_cb (ModestMailOperation *mail_op, 
2119                      TnyFolder *folder, 
2120                      gpointer user_data)
2121 {
2122         ModestMainWindow *win = NULL;
2123         GtkWidget *header_view;
2124
2125         g_return_if_fail (TNY_IS_FOLDER (folder));
2126
2127         win = MODEST_MAIN_WINDOW (user_data);
2128         header_view = 
2129                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2130
2131         if (header_view) {
2132                 TnyFolder *current_folder;
2133
2134                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2135                 if (current_folder != NULL && folder != current_folder) {
2136                         g_object_unref (current_folder);
2137                         return;
2138                 } else if (current_folder)
2139                         g_object_unref (current_folder);
2140         }
2141
2142         /* Check if folder is empty and set headers view contents style */
2143         if (tny_folder_get_all_count (folder) == 0)
2144                 modest_main_window_set_contents_style (win,
2145                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2146 }
2147
2148 void 
2149 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2150                                                TnyFolderStore *folder_store, 
2151                                                gboolean selected,
2152                                                ModestMainWindow *main_window)
2153 {
2154         ModestConf *conf;
2155         GtkWidget *header_view;
2156
2157         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2158
2159         header_view = modest_main_window_get_child_widget(main_window,
2160                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2161         if (!header_view)
2162                 return;
2163         
2164         conf = modest_runtime_get_conf ();
2165
2166         if (TNY_IS_ACCOUNT (folder_store)) {
2167                 if (selected) {
2168                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2169                         
2170                         /* Show account details */
2171                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2172                 }
2173         } else {
2174                 if (TNY_IS_FOLDER (folder_store) && selected) {
2175                         
2176                         /* Update the active account */
2177                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2178                         if (account) {
2179                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2180                                 g_object_unref (account);
2181                                 account = NULL;
2182                         }
2183
2184                         /* Set the header style by default, it could
2185                            be changed later by the refresh callback to
2186                            empty */
2187                         modest_main_window_set_contents_style (main_window, 
2188                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2189
2190                         /* Set folder on header view. This function
2191                            will call tny_folder_refresh_async so we
2192                            pass a callback that will be called when
2193                            finished. We use that callback to set the
2194                            empty view if there are no messages */
2195                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2196                                                        TNY_FOLDER (folder_store),
2197                                                        folder_refreshed_cb,
2198                                                        main_window);
2199                         
2200                         /* Restore configuration. We need to do this
2201                            *after* the set_folder because the widget
2202                            memory asks the header view about its
2203                            folder  */
2204                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2205                                                       G_OBJECT(header_view),
2206                                                       MODEST_CONF_HEADER_VIEW_KEY);
2207                 } else {
2208                         /* Update the active account */
2209                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2210                         /* Save only if we're seeing headers */
2211                         if (modest_main_window_get_contents_style (main_window) ==
2212                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2213                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2214                                                            MODEST_CONF_HEADER_VIEW_KEY);
2215                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2216                 }
2217         }
2218
2219         /* Update toolbar dimming state */
2220         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2221 }
2222
2223 void 
2224 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2225                                      ModestWindow *win)
2226 {
2227         GtkWidget *dialog;
2228         gchar *txt, *item;
2229         gboolean online;
2230
2231         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2232         
2233         online = tny_device_is_online (modest_runtime_get_device());
2234
2235         if (online) {
2236                 /* already online -- the item is simply not there... */
2237                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2238                                                  GTK_DIALOG_MODAL,
2239                                                  GTK_MESSAGE_WARNING,
2240                                                  GTK_BUTTONS_NONE,
2241                                                  _("The %s you selected cannot be found"),
2242                                                  item);
2243                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2244                 gtk_dialog_run (GTK_DIALOG(dialog));
2245         } else {
2246                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2247                                                       GTK_WINDOW (win),
2248                                                       GTK_DIALOG_MODAL,
2249                                                       _("mcen_bd_dialog_cancel"),
2250                                                       GTK_RESPONSE_REJECT,
2251                                                       _("mcen_bd_dialog_ok"),
2252                                                       GTK_RESPONSE_ACCEPT,
2253                                                       NULL);
2254                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2255                                          "Do you want to get online?"), item);
2256                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2257                                     gtk_label_new (txt), FALSE, FALSE, 0);
2258                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2259                 g_free (txt);
2260
2261                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2262                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2263                         /* TODO: Comment about why is this commented out: */
2264                         /* modest_platform_connect_and_wait (); */
2265                 }
2266         }
2267         gtk_widget_destroy (dialog);
2268 }
2269
2270 void
2271 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2272                                      ModestWindow *win)
2273 {
2274         /* g_message ("%s %s", __FUNCTION__, link); */
2275 }       
2276
2277
2278 void
2279 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2280                                         ModestWindow *win)
2281 {
2282         modest_platform_activate_uri (link);
2283 }
2284
2285 void
2286 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2287                                           ModestWindow *win)
2288 {
2289         modest_platform_show_uri_popup (link);
2290 }
2291
2292 void
2293 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2294                                              ModestWindow *win)
2295 {
2296         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2297 }
2298
2299 void
2300 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2301                                           const gchar *address,
2302                                           ModestWindow *win)
2303 {
2304         /* g_message ("%s %s", __FUNCTION__, address); */
2305 }
2306
2307 static void
2308 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2309                       TnyMsg *saved_draft,
2310                       gpointer user_data)
2311 {
2312         ModestMsgEditWindow *edit_window;
2313         ModestMainWindow *win;
2314
2315         /* FIXME. Make the header view sensitive again. This is a
2316          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2317          * for details */
2318         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2319                                          modest_runtime_get_window_mgr(), FALSE));
2320         if (win != NULL) {
2321                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2322                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2323                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2324         }
2325
2326         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2327
2328         /* It might not be a good idea to do nothing if there was an error,
2329          * so let's at least show a generic error banner. */
2330         /* TODO error while saving attachment, show "Saving draft failed" banner */
2331         if (modest_mail_operation_get_error (mail_op) != NULL) {
2332                 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_op))->message);
2333                 modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
2334         } else {
2335                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2336         }
2337         g_object_unref(edit_window);
2338 }
2339
2340 gboolean
2341 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2342 {
2343         TnyTransportAccount *transport_account;
2344         ModestMailOperation *mail_operation;
2345         MsgData *data;
2346         gchar *account_name, *from;
2347         ModestAccountMgr *account_mgr;
2348 /*      char *info_text; */
2349         gboolean had_error = FALSE;
2350         guint64 available_disk, expected_size;
2351         gint parts_count;
2352         guint64 parts_size;
2353         ModestMainWindow *win;
2354
2355         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2356         
2357         data = modest_msg_edit_window_get_msg_data (edit_window);
2358
2359         /* Check size */
2360         available_disk = modest_folder_available_space (NULL);
2361         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2362         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2363                                                  data->html_body,
2364                                                  parts_count,
2365                                                  parts_size);
2366
2367         if ((available_disk != -1) && expected_size > available_disk) {
2368                 modest_msg_edit_window_free_msg_data (edit_window, data);
2369
2370                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2371                 return FALSE;
2372         }
2373
2374         account_name = g_strdup (data->account_name);
2375         account_mgr = modest_runtime_get_account_mgr();
2376         if (!account_name)
2377                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2378         if (!account_name) 
2379                 account_name = modest_account_mgr_get_default_account (account_mgr);
2380         if (!account_name) {
2381                 g_printerr ("modest: no account found\n");
2382                 modest_msg_edit_window_free_msg_data (edit_window, data);
2383                 return FALSE;
2384         }
2385
2386         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2387                 account_name = g_strdup (data->account_name);
2388         }
2389
2390         transport_account =
2391                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2392                                       (modest_runtime_get_account_store(),
2393                                        account_name,
2394                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2395         if (!transport_account) {
2396                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2397                 g_free (account_name);
2398                 modest_msg_edit_window_free_msg_data (edit_window, data);
2399                 return FALSE;
2400         }
2401         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2402
2403         /* Create the mail operation */         
2404         mail_operation = modest_mail_operation_new (NULL);
2405         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2406
2407         modest_mail_operation_save_to_drafts (mail_operation,
2408                                               transport_account,
2409                                               data->draft_msg,
2410                                               from,
2411                                               data->to, 
2412                                               data->cc, 
2413                                               data->bcc,
2414                                               data->subject, 
2415                                               data->plain_body, 
2416                                               data->html_body,
2417                                               data->attachments,
2418                                               data->images,
2419                                               data->priority_flags,
2420                                               on_save_to_drafts_cb,
2421                                               g_object_ref(edit_window));
2422
2423         /* Use the main window as the parent of the banner, if the
2424            main window does not exist it won't be shown, if the parent
2425            window exists then it's properly shown. We don't use the
2426            editor window because it could be closed (save to drafts
2427            could happen after closing the window */
2428         win = (ModestMainWindow *)
2429                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2430         if (win) {
2431                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2432                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2433                 g_free (text);
2434         }
2435         modest_msg_edit_window_set_modified (edit_window, FALSE);
2436
2437         /* Frees */
2438         g_free (from);
2439         g_free (account_name);
2440         g_object_unref (G_OBJECT (transport_account));
2441         g_object_unref (G_OBJECT (mail_operation));
2442
2443         modest_msg_edit_window_free_msg_data (edit_window, data);
2444
2445         /* ** FIXME **
2446          * If the drafts folder is selected then make the header view
2447          * insensitive while the message is being saved to drafts
2448          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2449          * is not very clean but it avoids letting the drafts folder
2450          * in an inconsistent state: the user could edit the message
2451          * being saved and undesirable things would happen.
2452          * In the average case the user won't notice anything at
2453          * all. In the worst case (the user is editing a really big
2454          * file from Drafts) the header view will be insensitive
2455          * during the saving process (10 or 20 seconds, depending on
2456          * the message). Anyway this is just a quick workaround: once
2457          * we find a better solution it should be removed
2458          * See NB#65125 (commend #18) for details.
2459          */
2460         if (!had_error && win != NULL) {
2461                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2462                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2463                 if (view != NULL) {
2464                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2465                         if (folder) {
2466                                 if (modest_tny_folder_is_local_folder(folder)) {
2467                                         TnyFolderType folder_type;
2468                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2469                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2470                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2471                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2472                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2473                                         }
2474                                 }
2475                         }
2476                         if (folder != NULL) g_object_unref(folder);
2477                 }
2478         }
2479
2480         return !had_error;
2481 }
2482
2483 /* For instance, when clicking the Send toolbar button when editing a message: */
2484 gboolean
2485 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2486 {
2487         TnyTransportAccount *transport_account = NULL;
2488         gboolean had_error = FALSE;
2489         guint64 available_disk, expected_size;
2490         gint parts_count;
2491         guint64 parts_size;
2492
2493         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2494
2495         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2496                 return TRUE;
2497         
2498         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2499
2500         /* Check size */
2501         available_disk = modest_folder_available_space (NULL);
2502         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2503         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2504                                                  data->html_body,
2505                                                  parts_count,
2506                                                  parts_size);
2507
2508         if ((available_disk != -1) && expected_size > available_disk) {
2509                 modest_msg_edit_window_free_msg_data (edit_window, data);
2510
2511                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2512                 return FALSE;
2513         }
2514
2515         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2516         gchar *account_name = g_strdup (data->account_name);
2517         if (!account_name)
2518                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2519
2520         if (!account_name) 
2521                 account_name = modest_account_mgr_get_default_account (account_mgr);
2522                 
2523         if (!account_name) {
2524                 modest_msg_edit_window_free_msg_data (edit_window, data);
2525                 /* Run account setup wizard */
2526                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2527                         return TRUE;
2528                 }
2529         }
2530         
2531         /* Get the currently-active transport account for this modest account: */
2532         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2533                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2534                                                           (modest_runtime_get_account_store(),
2535                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2536         }
2537         
2538         if (!transport_account) {
2539                 modest_msg_edit_window_free_msg_data (edit_window, data);
2540                 /* Run account setup wizard */
2541                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2542                         return TRUE;
2543         }
2544         
2545         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2546
2547         /* Create the mail operation */
2548         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2549         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2550
2551         modest_mail_operation_send_new_mail (mail_operation,
2552                                              transport_account,
2553                                              data->draft_msg,
2554                                              from,
2555                                              data->to, 
2556                                              data->cc, 
2557                                              data->bcc,
2558                                              data->subject, 
2559                                              data->plain_body, 
2560                                              data->html_body,
2561                                              data->attachments,
2562                                              data->images,
2563                                              data->priority_flags);
2564
2565         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2566                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2567
2568
2569         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2570                 const GError *error = modest_mail_operation_get_error (mail_operation);
2571                 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2572                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2573                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2574                         had_error = TRUE;
2575                 }
2576         }
2577                                              
2578         /* Free data: */
2579         g_free (from);
2580         g_free (account_name);
2581         g_object_unref (G_OBJECT (transport_account));
2582         g_object_unref (G_OBJECT (mail_operation));
2583
2584         modest_msg_edit_window_free_msg_data (edit_window, data);
2585
2586         if (!had_error) {
2587                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2588
2589                 /* Save settings and close the window: */
2590                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2591         }
2592
2593         return !had_error;
2594 }
2595
2596 void 
2597 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2598                                   ModestMsgEditWindow *window)
2599 {
2600         ModestMsgEditFormatState *format_state = NULL;
2601
2602         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2603         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2604
2605         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2606                 return;
2607
2608         format_state = modest_msg_edit_window_get_format_state (window);
2609         g_return_if_fail (format_state != NULL);
2610
2611         format_state->bold = gtk_toggle_action_get_active (action);
2612         modest_msg_edit_window_set_format_state (window, format_state);
2613         g_free (format_state);
2614         
2615 }
2616
2617 void 
2618 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2619                                      ModestMsgEditWindow *window)
2620 {
2621         ModestMsgEditFormatState *format_state = NULL;
2622
2623         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2624         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2625
2626         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2627                 return;
2628
2629         format_state = modest_msg_edit_window_get_format_state (window);
2630         g_return_if_fail (format_state != NULL);
2631
2632         format_state->italics = gtk_toggle_action_get_active (action);
2633         modest_msg_edit_window_set_format_state (window, format_state);
2634         g_free (format_state);
2635         
2636 }
2637
2638 void 
2639 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2640                                      ModestMsgEditWindow *window)
2641 {
2642         ModestMsgEditFormatState *format_state = NULL;
2643
2644         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2645         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2646
2647         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2648                 return;
2649
2650         format_state = modest_msg_edit_window_get_format_state (window);
2651         g_return_if_fail (format_state != NULL);
2652
2653         format_state->bullet = gtk_toggle_action_get_active (action);
2654         modest_msg_edit_window_set_format_state (window, format_state);
2655         g_free (format_state);
2656         
2657 }
2658
2659 void 
2660 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2661                                      GtkRadioAction *selected,
2662                                      ModestMsgEditWindow *window)
2663 {
2664         ModestMsgEditFormatState *format_state = NULL;
2665         GtkJustification value;
2666
2667         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2668
2669         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2670                 return;
2671
2672         value = gtk_radio_action_get_current_value (selected);
2673
2674         format_state = modest_msg_edit_window_get_format_state (window);
2675         g_return_if_fail (format_state != NULL);
2676
2677         format_state->justification = value;
2678         modest_msg_edit_window_set_format_state (window, format_state);
2679         g_free (format_state);
2680 }
2681
2682 void 
2683 modest_ui_actions_on_select_editor_color (GtkAction *action,
2684                                           ModestMsgEditWindow *window)
2685 {
2686         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2687         g_return_if_fail (GTK_IS_ACTION (action));
2688
2689         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2690                 return;
2691
2692         modest_msg_edit_window_select_color (window);
2693 }
2694
2695 void 
2696 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2697                                                      ModestMsgEditWindow *window)
2698 {
2699         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2700         g_return_if_fail (GTK_IS_ACTION (action));
2701
2702         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2703                 return;
2704
2705         modest_msg_edit_window_select_background_color (window);
2706 }
2707
2708 void 
2709 modest_ui_actions_on_insert_image (GtkAction *action,
2710                                    ModestMsgEditWindow *window)
2711 {
2712         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2713         g_return_if_fail (GTK_IS_ACTION (action));
2714
2715         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2716                 return;
2717
2718         modest_msg_edit_window_insert_image (window);
2719 }
2720
2721 void 
2722 modest_ui_actions_on_attach_file (GtkAction *action,
2723                                   ModestMsgEditWindow *window)
2724 {
2725         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2726         g_return_if_fail (GTK_IS_ACTION (action));
2727
2728         modest_msg_edit_window_offer_attach_file (window);
2729 }
2730
2731 void 
2732 modest_ui_actions_on_remove_attachments (GtkAction *action,
2733                                          ModestMsgEditWindow *window)
2734 {
2735         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2736         g_return_if_fail (GTK_IS_ACTION (action));
2737
2738         modest_msg_edit_window_remove_attachments (window, NULL);
2739 }
2740
2741 static void
2742 do_create_folder_cb (ModestMailOperation *mail_op,
2743                      TnyFolderStore *parent_folder, 
2744                      TnyFolder *new_folder,
2745                      gpointer user_data)
2746 {
2747         gchar *suggested_name = (gchar *) user_data;
2748         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2749
2750         if (modest_mail_operation_get_error (mail_op)) {
2751                 /* Show an error */
2752                 modest_platform_information_banner (GTK_WIDGET (source_win), NULL,
2753                                                     _("mail_in_ui_folder_create_error"));
2754
2755                 /* Try again */
2756                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2757         } else {
2758                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2759                  * FIXME: any other? */         
2760                 GtkWidget *folder_view;
2761
2762                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2763                         folder_view = 
2764                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2765                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2766                 else
2767                         folder_view =
2768                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2769                 
2770                 /* Select the newly created folder */
2771                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2772                                                   new_folder, FALSE);
2773                 g_object_unref (new_folder);
2774         }
2775         /* Free. Note that the first time it'll be NULL so noop */
2776         g_free (suggested_name);
2777         g_object_unref (source_win);
2778 }
2779
2780 static void
2781 do_create_folder (GtkWindow *parent_window, 
2782                   TnyFolderStore *parent_folder, 
2783                   const gchar *suggested_name)
2784 {
2785         gint result;
2786         gchar *folder_name = NULL;
2787
2788         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2789                                                         parent_folder,
2790                                                         (gchar *) suggested_name,
2791                                                         &folder_name);
2792         
2793         if (result == GTK_RESPONSE_ACCEPT) {
2794                 ModestMailOperation *mail_op;
2795                 
2796                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2797                         
2798                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2799                                                  mail_op);
2800                 modest_mail_operation_create_folder (mail_op,
2801                                                      parent_folder,
2802                                                      (const gchar *) folder_name,
2803                                                      do_create_folder_cb,
2804                                                      folder_name);
2805                 g_object_unref (mail_op);
2806         }
2807 }
2808
2809 static void
2810 create_folder_performer (gboolean canceled, 
2811                          GError *err,
2812                          GtkWindow *parent_window, 
2813                          TnyAccount *account, 
2814                          gpointer user_data)
2815 {
2816         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2817
2818         if (canceled || err) {
2819                 goto frees;
2820         }
2821
2822         /* Run the new folder dialog */
2823         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2824
2825  frees:
2826         g_object_unref (parent_folder);
2827 }
2828
2829 static void
2830 modest_ui_actions_create_folder(GtkWidget *parent_window,
2831                                 GtkWidget *folder_view)
2832 {
2833         TnyFolderStore *parent_folder;
2834
2835         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2836         
2837         if (parent_folder) {
2838                 /* The parent folder will be freed in the callback */
2839                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2840                                                                TRUE,
2841                                                                parent_folder,
2842                                                                create_folder_performer, 
2843                                                                parent_folder);
2844         }
2845 }
2846
2847 void 
2848 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2849 {
2850         GtkWidget *folder_view;
2851         
2852         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2853
2854         folder_view = modest_main_window_get_child_widget (main_window,
2855                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2856         if (!folder_view)
2857                 return;
2858
2859         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2860 }
2861
2862 static void
2863 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2864                                                gpointer user_data)
2865 {
2866         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2867         const GError *error = NULL;
2868         const gchar *message = NULL;
2869         
2870         /* Get error message */
2871         error = modest_mail_operation_get_error (mail_op);
2872         if (!error)
2873                 g_return_if_reached ();
2874
2875         switch (error->code) {
2876         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2877                 message = _CS("ckdg_ib_folder_already_exists");
2878                 break;
2879         default:
2880                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2881                            error->code, error->message);
2882                 return;
2883         }
2884
2885         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2886 }
2887
2888 typedef struct {
2889         TnyFolderStore *folder;
2890         gchar *new_name;
2891 } RenameFolderInfo;
2892
2893 static void
2894 on_rename_folder_cb (ModestMailOperation *mail_op, 
2895                      TnyFolder *new_folder,
2896                      gpointer user_data)
2897 {
2898         /* Select now */
2899         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2900                                           new_folder, FALSE);
2901 }
2902
2903 static void
2904 on_rename_folder_performer (gboolean canceled, 
2905                             GError *err, 
2906                             GtkWindow *parent_window, 
2907                             TnyAccount *account, 
2908                             gpointer user_data)
2909 {
2910         ModestMailOperation *mail_op = NULL;
2911         GtkTreeSelection *sel = NULL;
2912         GtkWidget *folder_view = NULL;
2913         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2914
2915         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2916
2917                 folder_view = modest_main_window_get_child_widget (
2918                                 MODEST_MAIN_WINDOW (parent_window),
2919                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2920
2921                 mail_op = 
2922                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2923                                         modest_ui_actions_rename_folder_error_handler,
2924                                         parent_window, NULL);
2925
2926                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2927                                 mail_op);
2928
2929                 /* Clear the headers view */
2930                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2931                 gtk_tree_selection_unselect_all (sel);
2932
2933                 /* Actually rename the folder */
2934                 modest_mail_operation_rename_folder (mail_op,
2935                                                      TNY_FOLDER (data->folder),
2936                                                      (const gchar *) (data->new_name),
2937                                                      on_rename_folder_cb,
2938                                                      folder_view);
2939         }
2940
2941         g_object_unref (mail_op);
2942         g_free (data->new_name);
2943         g_free (data);
2944 }
2945
2946 void 
2947 modest_ui_actions_on_rename_folder (GtkAction *action,
2948                                      ModestMainWindow *main_window)
2949 {
2950         TnyFolderStore *folder;
2951         GtkWidget *folder_view;
2952         GtkWidget *header_view; 
2953
2954         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2955
2956         folder_view = modest_main_window_get_child_widget (main_window,
2957                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2958         if (!folder_view)
2959                 return;
2960
2961         header_view = modest_main_window_get_child_widget (main_window,
2962                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2963         
2964         if (!header_view)
2965                 return;
2966
2967         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2968
2969         if (!folder)
2970                 return;
2971
2972         if (TNY_IS_FOLDER (folder)) {
2973                 gchar *folder_name;
2974                 gint response;
2975                 const gchar *current_name;
2976                 TnyFolderStore *parent;
2977                 gboolean do_rename = TRUE;
2978
2979                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2980                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2981                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2982                                                                      parent, current_name, 
2983                                                                      &folder_name);
2984                 g_object_unref (parent);
2985
2986                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2987                         do_rename = FALSE;
2988                 } else {
2989                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2990                         rename_folder_data->folder = folder;
2991                         rename_folder_data->new_name = folder_name;
2992                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
2993                                         folder, on_rename_folder_performer, rename_folder_data);
2994                 }
2995         }
2996         g_object_unref (folder);
2997 }
2998
2999 static void
3000 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3001                                                gpointer user_data)
3002 {
3003         GObject *win = modest_mail_operation_get_source (mail_op);
3004
3005         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3006                                                 _("mail_in_ui_folder_delete_error"));
3007         g_object_unref (win);
3008 }
3009
3010 typedef struct {
3011         TnyFolderStore *folder;
3012         gboolean move_to_trash;
3013 } DeleteFolderInfo;
3014
3015 static void
3016 on_delete_folder_cb (gboolean canceled, 
3017                   GError *err,
3018                   GtkWindow *parent_window, 
3019                   TnyAccount *account, 
3020                   gpointer user_data)
3021 {
3022         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3023         GtkWidget *folder_view;
3024         ModestMailOperation *mail_op;
3025         GtkTreeSelection *sel;
3026         
3027         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3028                 g_object_unref (G_OBJECT (info->folder));
3029                 g_free (info);
3030                 return;
3031         }
3032         
3033         folder_view = modest_main_window_get_child_widget (
3034                         MODEST_MAIN_WINDOW (parent_window),
3035                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3036
3037         /* Unselect the folder before deleting it to free the headers */
3038         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3039         gtk_tree_selection_unselect_all (sel);
3040
3041         /* Create the mail operation */
3042         mail_op =
3043                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3044                                 modest_ui_actions_delete_folder_error_handler,
3045                                 NULL, NULL);
3046
3047         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3048                         mail_op);
3049         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3050         
3051         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3052
3053         g_object_unref (G_OBJECT (mail_op));
3054         g_object_unref (G_OBJECT (info->folder));
3055         g_free (info);
3056 }
3057
3058 static void
3059 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3060 {
3061         TnyFolderStore *folder;
3062         GtkWidget *folder_view;
3063         gint response;
3064         gchar *message;
3065         
3066         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3067
3068         folder_view = modest_main_window_get_child_widget (main_window,
3069                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3070         if (!folder_view)
3071                 return;
3072
3073         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3074
3075         /* Show an error if it's an account */
3076         if (!TNY_IS_FOLDER (folder)) {
3077                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3078                                                         _("mail_in_ui_folder_delete_error"));
3079                 g_object_unref (G_OBJECT (folder));
3080                 return;
3081         }
3082
3083         /* Ask the user */      
3084         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3085                                     tny_folder_get_name (TNY_FOLDER (folder)));
3086         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3087                                                             (const gchar *) message);
3088         g_free (message);
3089
3090         if (response == GTK_RESPONSE_OK) {
3091                 DeleteFolderInfo *info;
3092                 info = g_new0(DeleteFolderInfo, 1);
3093                 info->folder = folder;
3094                 info->move_to_trash = move_to_trash;
3095                 g_object_ref (G_OBJECT (info->folder));
3096                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3097                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3098                                                                TRUE,
3099                                                                TNY_FOLDER_STORE (account), 
3100                                                                on_delete_folder_cb, info);
3101                 g_object_unref (account);
3102         }
3103         g_object_unref (G_OBJECT (folder));
3104 }
3105
3106 void 
3107 modest_ui_actions_on_delete_folder (GtkAction *action,
3108                                      ModestMainWindow *main_window)
3109 {
3110         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3111         
3112         delete_folder (main_window, FALSE);
3113 }
3114
3115 void 
3116 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3117 {
3118         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3119         
3120         delete_folder (main_window, TRUE);
3121 }
3122
3123
3124 void
3125 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3126                                          const gchar* server_account_name,
3127                                          gchar **username,
3128                                          gchar **password, 
3129                                          gboolean *cancel, 
3130                                          gboolean *remember,
3131                                          ModestMainWindow *main_window)
3132 {
3133         g_return_if_fail(server_account_name);
3134         gboolean completed = FALSE;
3135         
3136         /* Initalize output parameters: */
3137         if (cancel)
3138                 *cancel = FALSE;
3139                 
3140         if (remember)
3141                 *remember = TRUE;
3142                 
3143 #ifdef MODEST_PLATFORM_MAEMO
3144         /* Maemo uses a different (awkward) button order,
3145          * It should probably just use gtk_alternative_dialog_button_order ().
3146          */
3147         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3148                                               NULL,
3149                                               GTK_DIALOG_MODAL,
3150                                               _("mcen_bd_dialog_ok"),
3151                                               GTK_RESPONSE_ACCEPT,
3152                                               _("mcen_bd_dialog_cancel"),
3153                                               GTK_RESPONSE_REJECT,
3154                                               NULL);
3155 #else
3156         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3157                                               NULL,
3158                                               GTK_DIALOG_MODAL,
3159                                               GTK_STOCK_CANCEL,
3160                                               GTK_RESPONSE_REJECT,
3161                                               GTK_STOCK_OK,
3162                                               GTK_RESPONSE_ACCEPT,
3163                                               NULL);
3164 #endif /* MODEST_PLATFORM_MAEMO */
3165
3166         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3167         
3168         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3169                 modest_runtime_get_account_mgr(), server_account_name);
3170         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3171                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3172                 if (cancel)
3173                         *cancel = TRUE;
3174                 return;
3175         }
3176         
3177         /* This causes a warning because the logical ID has no %s in it, 
3178          * though the translation does, but there is not much we can do about that: */
3179         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3180         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3181                             FALSE, FALSE, 0);
3182         g_free (txt);
3183         g_free (server_name);
3184         server_name = NULL;
3185
3186         /* username: */
3187         gchar *initial_username = modest_account_mgr_get_server_account_username (
3188                 modest_runtime_get_account_mgr(), server_account_name);
3189         
3190         GtkWidget *entry_username = gtk_entry_new ();
3191         if (initial_username)
3192                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3193         /* Dim this if a connection has ever succeeded with this username,
3194          * as per the UI spec: */
3195         const gboolean username_known = 
3196                 modest_account_mgr_get_server_account_username_has_succeeded(
3197                         modest_runtime_get_account_mgr(), server_account_name);
3198         gtk_widget_set_sensitive (entry_username, !username_known);
3199         
3200 #ifdef MODEST_PLATFORM_MAEMO
3201         /* Auto-capitalization is the default, so let's turn it off: */
3202         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3203         
3204         /* Create a size group to be used by all captions.
3205          * Note that HildonCaption does not create a default size group if we do not specify one.
3206          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3207         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3208         
3209         GtkWidget *caption = hildon_caption_new (sizegroup, 
3210                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3211         gtk_widget_show (entry_username);
3212         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3213                 FALSE, FALSE, MODEST_MARGIN_HALF);
3214         gtk_widget_show (caption);
3215 #else 
3216         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3217                             TRUE, FALSE, 0);
3218 #endif /* MODEST_PLATFORM_MAEMO */      
3219                             
3220         /* password: */
3221         GtkWidget *entry_password = gtk_entry_new ();
3222         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3223         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3224         
3225 #ifdef MODEST_PLATFORM_MAEMO
3226         /* Auto-capitalization is the default, so let's turn it off: */
3227         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3228                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3229         
3230         caption = hildon_caption_new (sizegroup, 
3231                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3232         gtk_widget_show (entry_password);
3233         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3234                 FALSE, FALSE, MODEST_MARGIN_HALF);
3235         gtk_widget_show (caption);
3236         g_object_unref (sizegroup);
3237 #else 
3238         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3239                             TRUE, FALSE, 0);
3240 #endif /* MODEST_PLATFORM_MAEMO */      
3241
3242         if (initial_username != NULL)
3243                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3244                                 
3245 /* This is not in the Maemo UI spec:
3246         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3247         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3248                             TRUE, FALSE, 0);
3249 */
3250
3251         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3252
3253         while (!completed) {
3254         
3255                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3256                         if (username) {
3257                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3258                                 
3259                                 /* Note that an empty field becomes the "" string */
3260                                 if (*username && strlen (*username) > 0) {
3261                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3262                                                                                         server_account_name, 
3263                                                                                         *username);
3264                                         completed = TRUE;
3265                                 
3266                                         const gboolean username_was_changed = 
3267                                                 (strcmp (*username, initial_username) != 0);
3268                                         if (username_was_changed) {
3269                                                 g_warning ("%s: tinymail does not yet support changing the "
3270                                                            "username in the get_password() callback.\n", __FUNCTION__);
3271                                         }
3272                                 } else {
3273                                         /* Show error */
3274                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3275                                                                             _("mcen_ib_username_pw_incorrect"));
3276                                         completed = FALSE;
3277                                 }
3278                         }
3279                         
3280                         if (password) {
3281                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3282                         
3283                                 /* We do not save the password in the configuration, 
3284                                  * because this function is only called for passwords that should 
3285                                  * not be remembered:
3286                                  modest_server_account_set_password (
3287                                  modest_runtime_get_account_mgr(), server_account_name, 
3288                                  *password);
3289                                  */
3290                         }                       
3291                         if (cancel)
3292                                 *cancel   = FALSE;                      
3293                 } else {
3294                         modest_platform_information_banner(GTK_WIDGET (dialog), 
3295                                                            NULL, _("mail_ib_login_cancelled"));
3296                         completed = TRUE;
3297                         if (username)
3298                                 *username = NULL;                       
3299                         if (password)
3300                                 *password = NULL;                       
3301                         if (cancel)
3302                                 *cancel   = TRUE;
3303                 }
3304         }
3305
3306 /* This is not in the Maemo UI spec:
3307         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3308                 *remember = TRUE;
3309         else
3310                 *remember = FALSE;
3311 */
3312
3313         gtk_widget_destroy (dialog);
3314         
3315         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3316 }
3317
3318 void
3319 modest_ui_actions_on_cut (GtkAction *action,
3320                           ModestWindow *window)
3321 {
3322         GtkWidget *focused_widget;
3323         GtkClipboard *clipboard;
3324
3325         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3326         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3327         if (GTK_IS_EDITABLE (focused_widget)) {
3328                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3329                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3330                 gtk_clipboard_store (clipboard);
3331         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3332                 GtkTextBuffer *buffer;
3333
3334                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3335                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3336                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3337                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3338                         gtk_clipboard_store (clipboard);
3339                 }
3340         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3341                 TnyList *header_list = modest_header_view_get_selected_headers (
3342                                 MODEST_HEADER_VIEW (focused_widget));
3343                 gboolean continue_download = FALSE;
3344                 gint num_of_unc_msgs;
3345
3346                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3347
3348                 if (num_of_unc_msgs) {
3349                         TnyAccount *account = get_account_from_header_list (header_list);
3350                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3351                         g_object_unref (account);
3352                 }
3353
3354                 if (num_of_unc_msgs == 0 || continue_download) {
3355 /*                      modest_platform_information_banner (
3356                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3357                         modest_header_view_cut_selection (
3358                                         MODEST_HEADER_VIEW (focused_widget));
3359                 }
3360
3361                 g_object_unref (header_list);
3362         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3363                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3364         }
3365 }
3366
3367 void
3368 modest_ui_actions_on_copy (GtkAction *action,
3369                            ModestWindow *window)
3370 {
3371         GtkClipboard *clipboard;
3372         GtkWidget *focused_widget;
3373         gboolean copied = TRUE;
3374
3375         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3376         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3377
3378         if (GTK_IS_LABEL (focused_widget)) {
3379                 gchar *selection;
3380                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3381                 gtk_clipboard_set_text (clipboard, selection, -1);
3382                 g_free (selection);
3383                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3384                 gtk_clipboard_store (clipboard);
3385         } else if (GTK_IS_EDITABLE (focused_widget)) {
3386                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3387                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3388                 gtk_clipboard_store (clipboard);
3389         } else if (GTK_IS_HTML (focused_widget)) {
3390                 gtk_html_copy (GTK_HTML (focused_widget));
3391                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3392                 gtk_clipboard_store (clipboard);
3393         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3394                 GtkTextBuffer *buffer;
3395                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3396                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3397                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3398                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3399                         gtk_clipboard_store (clipboard);
3400                 }
3401         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3402                 TnyList *header_list = modest_header_view_get_selected_headers (
3403                                 MODEST_HEADER_VIEW (focused_widget));
3404                 gboolean continue_download = FALSE;
3405                 gint num_of_unc_msgs;
3406
3407                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3408
3409                 if (num_of_unc_msgs) {
3410                         TnyAccount *account = get_account_from_header_list (header_list);
3411                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3412                         g_object_unref (account);
3413                 }
3414
3415                 if (num_of_unc_msgs == 0 || continue_download) {
3416                         modest_platform_information_banner (
3417                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3418                         modest_header_view_copy_selection (
3419                                         MODEST_HEADER_VIEW (focused_widget));
3420                 } else
3421                         copied = FALSE;
3422
3423                 g_object_unref (header_list);
3424
3425         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3426                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3427         }
3428
3429         /* Show information banner if there was a copy to clipboard */
3430         if(copied)
3431                 modest_platform_information_banner (
3432                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3433 }
3434
3435 void
3436 modest_ui_actions_on_undo (GtkAction *action,
3437                            ModestWindow *window)
3438 {
3439         ModestEmailClipboard *clipboard = NULL;
3440
3441         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3442                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3443         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3444                 /* Clear clipboard source */
3445                 clipboard = modest_runtime_get_email_clipboard ();
3446                 modest_email_clipboard_clear (clipboard);               
3447         }
3448         else {
3449                 g_return_if_reached ();
3450         }
3451 }
3452
3453 void
3454 modest_ui_actions_on_redo (GtkAction *action,
3455                            ModestWindow *window)
3456 {
3457         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3458                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3459         }
3460         else {
3461                 g_return_if_reached ();
3462         }
3463 }
3464
3465
3466 static void
3467 destroy_information_note (ModestMailOperation *mail_op, 
3468                           gpointer user_data)
3469 {
3470         /* destroy information note */
3471         gtk_widget_destroy (GTK_WIDGET(user_data));
3472 }
3473
3474 static void
3475 destroy_folder_information_note (ModestMailOperation *mail_op, 
3476                                  TnyFolder *new_folder,
3477                                  gpointer user_data)
3478 {
3479         /* destroy information note */
3480         gtk_widget_destroy (GTK_WIDGET(user_data));
3481 }
3482
3483
3484 static void
3485 paste_as_attachment_free (gpointer data)
3486 {
3487         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3488
3489         gtk_widget_destroy (helper->banner);
3490         g_object_unref (helper->banner);
3491         g_free (helper);
3492 }
3493
3494 static void
3495 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3496                             TnyHeader *header,
3497                             TnyMsg *msg,
3498                             gpointer userdata)
3499 {
3500         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3501         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3502
3503         if (msg == NULL)
3504                 return;
3505
3506         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3507         
3508 }
3509
3510 void
3511 modest_ui_actions_on_paste (GtkAction *action,
3512                             ModestWindow *window)
3513 {
3514         GtkWidget *focused_widget = NULL;
3515         GtkWidget *inf_note = NULL;
3516         ModestMailOperation *mail_op = NULL;
3517
3518         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3519         if (GTK_IS_EDITABLE (focused_widget)) {
3520                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3521         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3522                 ModestEmailClipboard *e_clipboard = NULL;
3523                 e_clipboard = modest_runtime_get_email_clipboard ();
3524                 if (modest_email_clipboard_cleared (e_clipboard)) {
3525                         GtkTextBuffer *buffer;
3526                         GtkClipboard *clipboard;
3527
3528                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3529                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3530                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3531                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3532                         ModestMailOperation *mail_op;
3533                         TnyFolder *src_folder;
3534                         TnyList *data;
3535                         gboolean delete;
3536                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3537                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3538                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3539                                                                            _CS("ckct_nw_pasting"));
3540                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3541                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3542                         if (helper->banner != NULL) {
3543                                 g_object_ref (G_OBJECT (helper->banner));
3544                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3545                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3546                         }
3547
3548                         if (data != NULL) {
3549                                 modest_mail_operation_get_msgs_full (mail_op, 
3550                                                                      data,
3551                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3552                                                                      helper,
3553                                                                      paste_as_attachment_free);
3554                         }
3555                 }
3556         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3557                 ModestEmailClipboard *clipboard = NULL;
3558                 TnyFolder *src_folder = NULL;
3559                 TnyFolderStore *folder_store = NULL;
3560                 TnyList *data = NULL;           
3561                 gboolean delete = FALSE;
3562                 
3563                 /* Check clipboard source */
3564                 clipboard = modest_runtime_get_email_clipboard ();
3565                 if (modest_email_clipboard_cleared (clipboard)) 
3566                         return;
3567                 
3568                 /* Get elements to paste */
3569                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3570
3571                 /* Create a new mail operation */
3572                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3573                 
3574                 /* Get destination folder */
3575                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3576
3577                 /* transfer messages  */
3578                 if (data != NULL) {
3579                         gint response = 0;
3580
3581                         /* Ask for user confirmation */
3582                         response = 
3583                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3584                                                                              TNY_FOLDER (folder_store), 
3585                                                                              delete,
3586                                                                              data);
3587                         
3588                         if (response == GTK_RESPONSE_OK) {
3589                                 /* Launch notification */
3590                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3591                                                                              _CS("ckct_nw_pasting"));
3592                                 if (inf_note != NULL)  {
3593                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3594                                         gtk_widget_show (GTK_WIDGET(inf_note));
3595                                 }
3596
3597                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3598                                 modest_mail_operation_xfer_msgs (mail_op, 
3599                                                                  data,
3600                                                                  TNY_FOLDER (folder_store),
3601                                                                  delete,
3602                                                                  destroy_information_note,
3603                                                                  inf_note);                             
3604                         } else {
3605                                 g_object_unref (mail_op);
3606                         }
3607                         
3608                 } else if (src_folder != NULL) {                        
3609                         /* Launch notification */
3610                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3611                                                                      _CS("ckct_nw_pasting"));
3612                         if (inf_note != NULL)  {
3613                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3614                                 gtk_widget_show (GTK_WIDGET(inf_note));
3615                         }
3616                         
3617                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3618                         modest_mail_operation_xfer_folder (mail_op, 
3619                                                            src_folder,
3620                                                            folder_store,
3621                                                            delete,
3622                                                            destroy_folder_information_note,
3623                                                            inf_note);
3624                 }
3625
3626                 /* Free */
3627                 if (data != NULL) 
3628                         g_object_unref (data);
3629                 if (src_folder != NULL) 
3630                         g_object_unref (src_folder);
3631                 if (folder_store != NULL) 
3632                         g_object_unref (folder_store);
3633         }
3634 }
3635
3636
3637 void
3638 modest_ui_actions_on_select_all (GtkAction *action,
3639                                  ModestWindow *window)
3640 {
3641         GtkWidget *focused_widget;
3642
3643         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3644         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3645                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3646         } else if (GTK_IS_LABEL (focused_widget)) {
3647                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3648         } else if (GTK_IS_EDITABLE (focused_widget)) {
3649                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3650         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3651                 GtkTextBuffer *buffer;
3652                 GtkTextIter start, end;
3653
3654                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3655                 gtk_text_buffer_get_start_iter (buffer, &start);
3656                 gtk_text_buffer_get_end_iter (buffer, &end);
3657                 gtk_text_buffer_select_range (buffer, &start, &end);
3658         } else if (GTK_IS_HTML (focused_widget)) {
3659                 gtk_html_select_all (GTK_HTML (focused_widget));
3660         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3661                 GtkWidget *header_view = focused_widget;
3662                 GtkTreeSelection *selection = NULL;
3663                 
3664                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3665                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3666                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3667                 }
3668                                 
3669                 /* Disable window dimming management */
3670                 modest_window_disable_dimming (MODEST_WINDOW(window));
3671                 
3672                 /* Select all messages */
3673                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3674                 gtk_tree_selection_select_all (selection);
3675
3676                 /* Set focuse on header view */
3677                 gtk_widget_grab_focus (header_view);
3678
3679
3680                 /* Enable window dimming management */
3681                 modest_window_enable_dimming (MODEST_WINDOW(window));
3682                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3683         }
3684
3685 }
3686
3687 void
3688 modest_ui_actions_on_mark_as_read (GtkAction *action,
3689                                    ModestWindow *window)
3690 {       
3691         g_return_if_fail (MODEST_IS_WINDOW(window));
3692                 
3693         /* Mark each header as read */
3694         do_headers_action (window, headers_action_mark_as_read, NULL);
3695 }