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 }
3696
3697 void
3698 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3699                                      ModestWindow *window)
3700 {       
3701         g_return_if_fail (MODEST_IS_WINDOW(window));
3702                 
3703         /* Mark each header as read */
3704         do_headers_action (window, headers_action_mark_as_unread, NULL);
3705 }
3706
3707 void
3708 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3709                                   GtkRadioAction *selected,
3710                                   ModestWindow *window)
3711 {
3712         gint value;
3713
3714         value = gtk_radio_action_get_current_value (selected);
3715         if (MODEST_IS_WINDOW (window)) {
3716                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3717         }
3718 }
3719
3720 void
3721 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3722                                                GtkRadioAction *selected,
3723                                                ModestWindow *window)
3724 {
3725         TnyHeaderFlags flags;
3726         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3727
3728         flags = gtk_radio_action_get_current_value (selected);
3729         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3730 }
3731
3732 void
3733 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3734                                                   GtkRadioAction *selected,
3735                                                   ModestWindow *window)
3736 {
3737         gint file_format;
3738
3739         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3740
3741         file_format = gtk_radio_action_get_current_value (selected);
3742         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3743 }
3744
3745
3746 void
3747 modest_ui_actions_on_zoom_plus (GtkAction *action,
3748                                 ModestWindow *window)
3749 {
3750         g_return_if_fail (MODEST_IS_WINDOW (window));
3751
3752         modest_window_zoom_plus (MODEST_WINDOW (window));
3753 }
3754
3755 void     
3756 modest_ui_actions_on_zoom_minus (GtkAction *action,
3757                                  ModestWindow *window)
3758 {
3759         g_return_if_fail (MODEST_IS_WINDOW (window));
3760
3761         modest_window_zoom_minus (MODEST_WINDOW (window));
3762 }
3763
3764 void     
3765 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3766                                            ModestWindow *window)
3767 {
3768         ModestWindowMgr *mgr;
3769         gboolean fullscreen, active;
3770         g_return_if_fail (MODEST_IS_WINDOW (window));
3771
3772         mgr = modest_runtime_get_window_mgr ();
3773
3774         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3775         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3776
3777         if (active != fullscreen) {
3778                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3779                 gtk_window_present (GTK_WINDOW (window));
3780         }
3781 }
3782
3783 void
3784 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3785                                         ModestWindow *window)
3786 {
3787         ModestWindowMgr *mgr;
3788         gboolean fullscreen;
3789
3790         g_return_if_fail (MODEST_IS_WINDOW (window));
3791
3792         mgr = modest_runtime_get_window_mgr ();
3793         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3794         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3795
3796         gtk_window_present (GTK_WINDOW (window));
3797 }
3798
3799 /* 
3800  * Used by modest_ui_actions_on_details to call do_headers_action 
3801  */
3802 static void
3803 headers_action_show_details (TnyHeader *header, 
3804                              ModestWindow *window,
3805                              gpointer user_data)
3806
3807 {
3808         GtkWidget *dialog;
3809         
3810         /* Create dialog */
3811         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3812
3813         /* Run dialog */
3814         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3815         gtk_widget_show_all (dialog);
3816         gtk_dialog_run (GTK_DIALOG (dialog));
3817
3818         gtk_widget_destroy (dialog);
3819 }
3820
3821 /*
3822  * Show the folder details in a ModestDetailsDialog widget
3823  */
3824 static void
3825 show_folder_details (TnyFolder *folder, 
3826                      GtkWindow *window)
3827 {
3828         GtkWidget *dialog;
3829         
3830         /* Create dialog */
3831         dialog = modest_details_dialog_new_with_folder (window, folder);
3832
3833         /* Run dialog */
3834         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3835         gtk_widget_show_all (dialog);
3836         gtk_dialog_run (GTK_DIALOG (dialog));
3837
3838         gtk_widget_destroy (dialog);
3839 }
3840
3841 /*
3842  * Show the header details in a ModestDetailsDialog widget
3843  */
3844 void     
3845 modest_ui_actions_on_details (GtkAction *action, 
3846                               ModestWindow *win)
3847 {
3848         TnyList * headers_list;
3849         TnyIterator *iter;
3850         TnyHeader *header;              
3851
3852         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3853                 TnyMsg *msg;
3854
3855                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3856                 if (!msg)
3857                         return;
3858                 g_object_unref (msg);           
3859
3860                 headers_list = get_selected_headers (win);
3861                 if (!headers_list)
3862                         return;
3863
3864                 iter = tny_list_create_iterator (headers_list);
3865
3866                 header = TNY_HEADER (tny_iterator_get_current (iter));
3867                 if (header) {
3868                         headers_action_show_details (header, win, NULL);
3869                         g_object_unref (header);
3870                 }
3871
3872                 g_object_unref (iter);
3873                 g_object_unref (headers_list);
3874
3875         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3876                 GtkWidget *folder_view, *header_view;
3877
3878                 /* Check which widget has the focus */
3879                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3880                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3881                 if (gtk_widget_is_focus (folder_view)) {
3882                         TnyFolderStore *folder_store
3883                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3884                         if (!folder_store) {
3885                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3886                                 return; 
3887                         }
3888                         /* Show only when it's a folder */
3889                         /* This function should not be called for account items, 
3890                          * because we dim the menu item for them. */
3891                         if (TNY_IS_FOLDER (folder_store)) {
3892                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3893                         }
3894
3895                         g_object_unref (folder_store);
3896
3897                 } else {
3898                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3899                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3900                         /* Show details of each header */
3901                         do_headers_action (win, headers_action_show_details, header_view);
3902                 }
3903         }
3904 }
3905
3906 void     
3907 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3908                                      ModestMsgEditWindow *window)
3909 {
3910         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3911
3912         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3913 }
3914
3915 void     
3916 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3917                                       ModestMsgEditWindow *window)
3918 {
3919         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3920
3921         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3922 }
3923
3924 void
3925 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3926                                        ModestMainWindow *main_window)
3927 {
3928         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3929
3930         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3931                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3932         else
3933                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3934 }
3935
3936 void 
3937 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3938                                      ModestWindow *window)
3939 {
3940         gboolean active, fullscreen = FALSE;
3941         ModestWindowMgr *mgr;
3942
3943         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3944
3945         /* Check if we want to toggle the toolbar vuew in fullscreen
3946            or normal mode */
3947         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3948                      "ViewShowToolbarFullScreen")) {
3949                 fullscreen = TRUE;
3950         }
3951
3952         /* Toggle toolbar */
3953         mgr = modest_runtime_get_window_mgr ();
3954         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3955 }
3956
3957 void     
3958 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3959                                            ModestMsgEditWindow *window)
3960 {
3961         modest_msg_edit_window_select_font (window);
3962 }
3963
3964
3965 void
3966 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3967                                                   const gchar *display_name,
3968                                                   GtkWindow *window)
3969 {
3970         /* don't update the display name if it was already set;
3971          * updating the display name apparently is expensive */
3972         const gchar* old_name = gtk_window_get_title (window);
3973
3974         if (display_name == NULL)
3975                 display_name = " ";
3976
3977         if (old_name && display_name && strcmp (old_name, display_name) == 0)
3978                 return; /* don't do anything */
3979
3980         /* This is usually used to change the title of the main window, which
3981          * is the one that holds the folder view. Note that this change can
3982          * happen even when the widget doesn't have the focus. */
3983         gtk_window_set_title (window, display_name);
3984
3985 }
3986
3987 void
3988 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3989 {
3990         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3991         modest_msg_edit_window_select_contacts (window);
3992 }
3993
3994 void
3995 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3996 {
3997         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3998         modest_msg_edit_window_check_names (window, FALSE);
3999 }
4000
4001 static void
4002 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4003 {
4004         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4005                                          GTK_WIDGET (user_data));
4006 }
4007
4008 /*
4009  * This function is used to track changes in the selection of the
4010  * folder view that is inside the "move to" dialog to enable/disable
4011  * the OK button because we do not want the user to select a disallowed
4012  * destination for a folder.
4013  * The user also not desired to be able to use NEW button on items where
4014  * folder creation is not possibel.
4015  */
4016 static void
4017 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4018                                             TnyFolderStore *folder_store,
4019                                             gboolean selected,
4020                                             gpointer user_data)
4021 {
4022         GtkWidget *dialog = NULL;
4023         GtkWidget *ok_button = NULL, *new_button = NULL;
4024         GList *children = NULL;
4025         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4026         gboolean moving_folder = FALSE;
4027         gboolean is_local_account = TRUE;
4028         GtkWidget *folder_view = NULL;
4029         ModestTnyFolderRules rules;
4030
4031         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4032         
4033         if (!selected)
4034                 return;
4035         
4036         /* Get the OK button */
4037         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4038         if (!dialog)
4039                 return;
4040
4041         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4042         ok_button = GTK_WIDGET (children->next->next->data);
4043         new_button = GTK_WIDGET (children->next->data);
4044         g_list_free (children);
4045
4046         /* check if folder_store is an remote account */
4047         if (TNY_IS_ACCOUNT (folder_store)) {
4048                 TnyAccount *local_account = NULL;
4049                 TnyAccount *mmc_account = NULL;
4050                 ModestTnyAccountStore *account_store = NULL;
4051
4052                 account_store = modest_runtime_get_account_store ();
4053                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4054                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4055
4056                 if ((gpointer) local_account != (gpointer) folder_store &&
4057                     (gpointer) mmc_account != (gpointer) folder_store) {
4058                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4059                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4060                         if (proto_name != NULL) {
4061                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4062                         }
4063                         is_local_account = FALSE;
4064                         /* New button should be dimmed on remote
4065                            POP account root */
4066                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4067                 }
4068                 g_object_unref (local_account);
4069                 g_object_unref (mmc_account);
4070         }
4071
4072         /* Check the target folder rules */
4073         if (TNY_IS_FOLDER (folder_store)) {
4074                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4075                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4076                         ok_sensitive = FALSE;
4077                         new_sensitive = FALSE;
4078                         goto end;
4079                 }
4080         }
4081
4082         /* Check if we're moving a folder */
4083         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4084                 /* Get the widgets */
4085                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4086                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4087                 if (gtk_widget_is_focus (folder_view))
4088                         moving_folder = TRUE;
4089         }
4090
4091         if (moving_folder) {
4092                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4093
4094                 /* Get the folder to move */
4095                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4096                 
4097                 /* Check that we're not moving to the same folder */
4098                 if (TNY_IS_FOLDER (moved_folder)) {
4099                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4100                         if (parent == folder_store)
4101                                 ok_sensitive = FALSE;
4102                         g_object_unref (parent);
4103                 } 
4104
4105                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4106                         /* Do not allow to move to an account unless it's the
4107                            local folders account */
4108                         if (!is_local_account)
4109                                 ok_sensitive = FALSE;
4110                 } 
4111
4112                 if (ok_sensitive && (moved_folder == folder_store)) {
4113                         /* Do not allow to move to itself */
4114                         ok_sensitive = FALSE;
4115                 }
4116                 g_object_unref (moved_folder);
4117         } else {
4118                 TnyFolder *src_folder = NULL;
4119
4120                 /* Moving a message */
4121                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4122
4123                         TnyHeader *header = NULL;
4124                         header = modest_msg_view_window_get_header
4125                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4126                         if (!TNY_IS_HEADER(header))
4127                                 g_warning ("%s: could not get source header", __FUNCTION__);
4128                         else
4129                                 src_folder = tny_header_get_folder (header);
4130
4131                         if (header)
4132                                 g_object_unref (header);
4133                 } else {
4134                         src_folder = 
4135                                 TNY_FOLDER (modest_folder_view_get_selected
4136                                             (MODEST_FOLDER_VIEW (folder_view)));
4137                 }
4138
4139                 if (TNY_IS_FOLDER(src_folder)) {
4140                         /* Do not allow to move the msg to the same folder */
4141                         /* Do not allow to move the msg to an account */
4142                         if ((gpointer) src_folder == (gpointer) folder_store ||
4143                             TNY_IS_ACCOUNT (folder_store))
4144                                 ok_sensitive = FALSE;
4145                         g_object_unref (src_folder);
4146                 } else
4147                         g_warning ("%s: could not get source folder", __FUNCTION__);
4148         }
4149
4150  end:
4151         /* Set sensitivity of the OK button */
4152         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4153         /* Set sensitivity of the NEW button */
4154         gtk_widget_set_sensitive (new_button, new_sensitive);
4155 }
4156
4157
4158 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4159
4160 static GtkWidget*
4161 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4162 {
4163         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4164                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4165 }
4166
4167 static GtkWidget*
4168 create_move_to_dialog (GtkWindow *win,
4169                        GtkWidget *folder_view,
4170                        GtkWidget **tree_view)
4171 {
4172         GtkWidget *dialog, *scroll;
4173         GtkWidget *new_button;
4174
4175         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4176                                               GTK_WINDOW (win),
4177                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4178                                               NULL);
4179
4180         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4181         /* We do this manually so GTK+ does not associate a response ID for
4182          * the button. */
4183         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4184         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4185         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4186
4187         /* Create scrolled window */
4188         scroll = gtk_scrolled_window_new (NULL, NULL);
4189         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4190                                          GTK_POLICY_AUTOMATIC,
4191                                          GTK_POLICY_AUTOMATIC);
4192
4193         /* Create folder view */
4194         *tree_view = modest_platform_create_folder_view (NULL);
4195
4196         /* Track changes in the selection to
4197          * disable the OK button whenever "Move to" is not possible
4198          * disbale NEW button whenever New is not possible */
4199         g_signal_connect (*tree_view,
4200                           "folder_selection_changed",
4201                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4202                           win);
4203
4204         /* Listen to clicks on New button */
4205         g_signal_connect (G_OBJECT (new_button), 
4206                           "clicked", 
4207                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4208                           *tree_view);
4209
4210         /* It could happen that we're trying to move a message from a
4211            window (msg window for example) after the main window was
4212            closed, so we can not just get the model of the folder
4213            view */
4214         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4215                 const gchar *visible_id = NULL;
4216
4217                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4218                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4219                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4220                                                MODEST_FOLDER_VIEW(*tree_view));
4221
4222                 visible_id = 
4223                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4224
4225                 /* Show the same account than the one that is shown in the main window */
4226                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4227                                                                              visible_id);
4228         } else {
4229                 const gchar *active_account_name = NULL;
4230                 ModestAccountMgr *mgr = NULL;
4231                 ModestAccountSettings *settings = NULL;
4232                 ModestServerAccountSettings *store_settings = NULL;
4233
4234                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4235                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4236                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4237                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4238
4239                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4240                 mgr = modest_runtime_get_account_mgr ();
4241                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4242
4243                 if (settings) {
4244                         const gchar *store_account_name;
4245                         store_settings = modest_account_settings_get_store_settings (settings);
4246                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4247
4248                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4249                                                                                      store_account_name);
4250                         g_object_unref (store_settings);
4251                         g_object_unref (settings);
4252                 }
4253         }
4254
4255         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4256          *   get_folder_view_from_move_to_dialog 
4257          * (see above) later (needed for focus handling) 
4258          */
4259         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4260
4261         
4262         /* Hide special folders */
4263         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4264
4265         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4266
4267         /* Add scroll to dialog */
4268         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4269                             scroll, TRUE, TRUE, 0);
4270
4271         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4272         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4273
4274         return dialog;
4275 }
4276
4277 /*
4278  * Returns TRUE if at least one of the headers of the list belongs to
4279  * a message that has been fully retrieved.
4280  */
4281 #if 0 /* no longer in use. delete in 2007.10 */
4282 static gboolean
4283 has_retrieved_msgs (TnyList *list)
4284 {
4285         TnyIterator *iter;
4286         gboolean found = FALSE;
4287
4288         iter = tny_list_create_iterator (list);
4289         while (!tny_iterator_is_done (iter) && !found) {
4290                 TnyHeader *header;
4291                 TnyHeaderFlags flags = 0;
4292
4293                 header = TNY_HEADER (tny_iterator_get_current (iter));
4294                 if (header) {
4295                         flags = tny_header_get_flags (header);
4296                         if (flags & TNY_HEADER_FLAG_CACHED)
4297 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4298                                 found = TRUE;
4299
4300                         g_object_unref (header);
4301                 }
4302
4303                 if (!found)
4304                         tny_iterator_next (iter);
4305         }
4306         g_object_unref (iter);
4307
4308         return found;
4309 }
4310 #endif /* 0 */
4311
4312
4313 /*
4314  * Shows a confirmation dialog to the user when we're moving messages
4315  * from a remote server to the local storage. Returns the dialog
4316  * response. If it's other kind of movement then it always returns
4317  * GTK_RESPONSE_OK
4318  *
4319  * This one is used by the next functions:
4320  *      modest_ui_actions_on_paste                      - commented out
4321  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4322  */
4323 gint
4324 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4325                                              TnyFolder *dest_folder,
4326                                              gboolean delete,
4327                                              TnyList *headers)
4328 {
4329         gint response = GTK_RESPONSE_OK;
4330         TnyAccount *account = NULL;
4331         TnyFolder *src_folder = NULL;
4332         TnyIterator *iter = NULL;
4333         TnyHeader *header = NULL;
4334
4335         /* return with OK if the destination is a remote folder */
4336         if (modest_tny_folder_is_remote_folder (dest_folder))
4337                 return GTK_RESPONSE_OK;
4338
4339         /* Get source folder */
4340         iter = tny_list_create_iterator (headers);
4341         header = TNY_HEADER (tny_iterator_get_current (iter));
4342         if (header) {
4343                 src_folder = tny_header_get_folder (header);
4344                 g_object_unref (header);
4345         }
4346         g_object_unref (iter);
4347
4348         /* if no src_folder, message may be an attahcment */
4349         if (src_folder == NULL) 
4350                 return GTK_RESPONSE_CANCEL;
4351
4352         /* If the source is a local or MMC folder */
4353         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4354                 g_object_unref (src_folder);
4355                 return GTK_RESPONSE_OK;
4356         }
4357
4358         /* Get the account */
4359         account = tny_folder_get_account (src_folder);
4360
4361         /* now if offline we ask the user */
4362         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4363                 response = GTK_RESPONSE_OK;
4364         else
4365                 response = GTK_RESPONSE_CANCEL;
4366
4367         /* Frees */
4368         g_object_unref (src_folder);
4369         g_object_unref (account);
4370
4371         return response;
4372 }
4373
4374 static void
4375 move_to_cb (ModestMailOperation *mail_op, 
4376             gpointer user_data)
4377 {
4378         MoveToHelper *helper = (MoveToHelper *) user_data;
4379
4380         /* Note that the operation could have failed, in that case do
4381            nothing */
4382         if (modest_mail_operation_get_status (mail_op) == 
4383             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4384
4385                 GObject *object = modest_mail_operation_get_source (mail_op);
4386                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4387                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4388
4389                         if (!modest_msg_view_window_select_next_message (self) &&
4390                             !modest_msg_view_window_select_previous_message (self)) {
4391                                 /* No more messages to view, so close this window */
4392                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4393                         }
4394                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4395                         GtkWidget *header_view;
4396                         GtkTreePath *path;
4397                         GtkTreeSelection *sel;
4398
4399                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4400                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4401                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4402                         path = gtk_tree_row_reference_get_path (helper->reference);
4403                         gtk_tree_selection_select_path (sel, path);
4404                         gtk_tree_path_free (path);
4405                 }
4406                 g_object_unref (object);
4407         }
4408
4409         /* Close the "Pasting" information banner */
4410         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4411         if (helper->reference != NULL)
4412                 gtk_tree_row_reference_free (helper->reference);
4413         g_free (helper);
4414 }
4415
4416 static void
4417 folder_move_to_cb (ModestMailOperation *mail_op, 
4418                    TnyFolder *new_folder,
4419                    gpointer user_data)
4420 {
4421         GtkWidget *folder_view;
4422         GObject *object;
4423
4424         object = modest_mail_operation_get_source (mail_op);
4425         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4426                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4427         g_object_ref (folder_view);
4428         g_object_unref (object);
4429         move_to_cb (mail_op, user_data);
4430         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4431         g_object_unref (folder_view);
4432 }
4433
4434 static void
4435 msgs_move_to_cb (ModestMailOperation *mail_op, 
4436                  gpointer user_data)
4437 {
4438         move_to_cb (mail_op, user_data);
4439 }
4440
4441 void
4442 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4443                                              gpointer user_data)
4444 {
4445         ModestWindow *main_window = NULL;
4446         GObject *win = NULL;
4447         
4448         /* Disable next automatic folder selection */
4449         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4450                                                          FALSE); /* don't create */
4451         if (main_window) {
4452                 GtkWidget *folder_view = NULL;
4453         
4454                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4455                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4456                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4457                 
4458                 if (user_data && TNY_IS_FOLDER (user_data)) {
4459                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4460                                                           TNY_FOLDER (user_data), FALSE);
4461                 }
4462         }
4463
4464         /* Show notification dialog */
4465         win = modest_mail_operation_get_source (mail_op);
4466         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4467         if (win)
4468                 g_object_unref (win);
4469 }
4470
4471 void
4472 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4473                                               gpointer user_data)
4474 {
4475         GObject *win = modest_mail_operation_get_source (mail_op);
4476         const GError *error = modest_mail_operation_get_error (mail_op);
4477
4478         g_return_if_fail (error != NULL);
4479         if (error->message != NULL)             
4480                 g_printerr ("modest: %s\n", error->message);
4481         else
4482                 g_printerr ("modest: unkonw error on send&receive operation");
4483
4484         /* Show error message */
4485 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4486 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4487 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4488 /*      else  */
4489 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4490 /*                                                      _CS("sfil_ib_unable_to_send")); */
4491         g_object_unref (win);
4492 }
4493
4494 static void
4495 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4496                        TnyHeader *header, 
4497                        gboolean canceled,
4498                        TnyMsg *msg, 
4499                        GError *err,
4500                        gpointer user_data)
4501 {
4502         TnyList *parts;
4503         TnyIterator *iter;
4504         gint pending_purges = 0;
4505         gboolean some_purged = FALSE;
4506         ModestWindow *win = MODEST_WINDOW (user_data);
4507         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4508
4509         /* If there was any error */
4510         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4511                 modest_window_mgr_unregister_header (mgr, header);
4512                 return;
4513         }
4514
4515         /* Once the message has been retrieved for purging, we check if
4516          * it's all ok for purging */
4517
4518         parts = tny_simple_list_new ();
4519         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4520         iter = tny_list_create_iterator (parts);
4521
4522         while (!tny_iterator_is_done (iter)) {
4523                 TnyMimePart *part;
4524                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4525                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4526                         if (tny_mime_part_is_purged (part))
4527                                 some_purged = TRUE;
4528                         else
4529                                 pending_purges++;
4530                 }
4531
4532                 if (part)
4533                         g_object_unref (part);
4534
4535                 tny_iterator_next (iter);
4536         }
4537         g_object_unref (iter);
4538         
4539
4540         if (pending_purges>0) {
4541                 gint response;
4542                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4543
4544                 if (response == GTK_RESPONSE_OK) {
4545                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4546                         iter = tny_list_create_iterator (parts);
4547                         while (!tny_iterator_is_done (iter)) {
4548                                 TnyMimePart *part;
4549                                 
4550                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4551                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4552                                         tny_mime_part_set_purged (part);
4553
4554                                 if (part)
4555                                         g_object_unref (part);
4556
4557                                 tny_iterator_next (iter);
4558                         }
4559                         g_object_unref (iter);
4560                         
4561                         tny_msg_rewrite_cache (msg);
4562                 }
4563      /* } else { */
4564                 /* This string no longer exists, refer to NB#75415 for more info */
4565                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4566         }
4567
4568         modest_window_mgr_unregister_header (mgr, header);
4569
4570         g_object_unref (parts);
4571 }
4572
4573 static void
4574 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4575                                                      ModestMainWindow *win)
4576 {
4577         GtkWidget *header_view;
4578         TnyList *header_list;
4579         TnyHeader *header;
4580         TnyHeaderFlags flags;
4581         ModestWindow *msg_view_window =  NULL;
4582         gboolean found;
4583
4584         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4585
4586         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4587                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4588
4589         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4590         if (!header_list) {
4591                 g_warning ("%s: no header selected", __FUNCTION__);
4592                 return;
4593         }
4594         
4595         if (tny_list_get_length (header_list) == 1) {
4596                 TnyIterator *iter = tny_list_create_iterator (header_list);
4597                 header = TNY_HEADER (tny_iterator_get_current (iter));
4598                 g_object_unref (iter);
4599         } else
4600                 return;
4601         
4602         if (!header || !TNY_IS_HEADER(header)) {
4603                 g_warning ("%s: header is not valid", __FUNCTION__);
4604                 return;
4605         }
4606         
4607         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4608                                                           header, &msg_view_window);
4609         flags = tny_header_get_flags (header);
4610         if (!(flags & TNY_HEADER_FLAG_CACHED))
4611                 return;
4612         if (found) {
4613                 if (msg_view_window != NULL) 
4614                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4615                 else {
4616                         /* do nothing; uid was registered before, so window is probably on it's way */
4617                         g_warning ("debug: header %p has already been registered", header);
4618                 }
4619         } else {
4620                 ModestMailOperation *mail_op = NULL;
4621                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4622                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4623                                                                          modest_ui_actions_get_msgs_full_error_handler,
4624                                                                          NULL, NULL);
4625                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4626                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4627                 
4628                 g_object_unref (mail_op);
4629         }
4630         if (header)
4631                 g_object_unref (header);
4632         if (header_list)
4633                 g_object_unref (header_list);
4634 }
4635
4636 /*
4637  * Checks if we need a connection to do the transfer and if the user
4638  * wants to connect to complete it
4639  */
4640 void
4641 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4642                                        TnyFolderStore *src_folder,
4643                                        TnyList *headers,
4644                                        TnyFolder *dst_folder,
4645                                        gboolean delete_originals,
4646                                        gboolean *need_connection,
4647                                        gboolean *do_xfer)
4648 {
4649         TnyAccount *src_account;
4650         gint uncached_msgs = 0;
4651
4652         uncached_msgs = header_list_count_uncached_msgs (headers);
4653
4654         /* We don't need any further check if
4655          *
4656          * 1- the source folder is local OR
4657          * 2- the device is already online
4658          */
4659         if (!modest_tny_folder_store_is_remote (src_folder) ||
4660             tny_device_is_online (modest_runtime_get_device())) {
4661                 *need_connection = FALSE;
4662                 *do_xfer = TRUE;
4663                 return;
4664         }
4665
4666         /* We must ask for a connection when
4667          *
4668          *   - the message(s) is not already cached   OR 
4669          *   - the message(s) is cached but the leave_on_server setting
4670          * is FALSE (because we need to sync the source folder to
4671          * delete the message from the server (for IMAP we could do it
4672          * offline, it'll take place the next time we get a
4673          * connection)
4674          */
4675         src_account = get_account_from_folder_store (src_folder);
4676         if (uncached_msgs > 0) {
4677                 guint num_headers;
4678                 const gchar *msg;
4679
4680                 *need_connection = TRUE;
4681                 num_headers = tny_list_get_length (headers);
4682                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4683
4684                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4685                     GTK_RESPONSE_CANCEL) {
4686                         *do_xfer = FALSE;
4687                 } else {
4688                         *do_xfer = TRUE;
4689                 }
4690         } else {
4691                 /* The transfer is possible and the user wants to */
4692                 *do_xfer = TRUE;
4693
4694                 if (remote_folder_is_pop (src_folder) && delete_originals) {
4695                         const gchar *account_name;
4696                         gboolean leave_on_server;
4697                         
4698                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4699                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4700                                                                                   account_name);
4701                         
4702                         if (leave_on_server == TRUE) {
4703                                 *need_connection = FALSE;
4704                         } else {
4705                                 *need_connection = TRUE;
4706                         }
4707                 } else {
4708                         *need_connection = FALSE;
4709                 }
4710         }
4711
4712         /* Frees */
4713         g_object_unref (src_account);
4714 }
4715
4716
4717 /**
4718  * Utility function that transfer messages from both the main window
4719  * and the msg view window when using the "Move to" dialog
4720  */
4721 static void
4722 xfer_messages_performer  (gboolean canceled, 
4723                           GError *err,
4724                           GtkWindow *parent_window, 
4725                           TnyAccount *account, 
4726                           gpointer user_data)
4727 {
4728         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4729         ModestWindow *win = MODEST_WINDOW (parent_window);
4730         TnyList *headers = NULL;
4731         TnyAccount *dst_account = NULL;
4732         const gchar *proto_str = NULL;
4733         gboolean dst_is_pop = FALSE;
4734
4735         if (canceled || err) {
4736                 /* Show the proper error message */
4737                 modest_ui_actions_on_account_connection_error (parent_window, account);
4738                 g_object_unref (dst_folder);
4739                 return;
4740         }
4741
4742         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4743         proto_str = tny_account_get_proto (dst_account);
4744
4745         /* tinymail will return NULL for local folders it seems */
4746         dst_is_pop = proto_str &&
4747                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4748                  MODEST_PROTOCOL_STORE_POP);
4749
4750         g_object_unref (dst_account);
4751
4752         /* Get selected headers */
4753         headers = get_selected_headers (MODEST_WINDOW (win));
4754         if (!headers) {
4755                 g_warning ("%s: no headers selected", __FUNCTION__);
4756                 return;
4757         }
4758
4759
4760         if (dst_is_pop) {
4761                 modest_platform_information_banner (GTK_WIDGET (win),
4762                                                     NULL,
4763                                                     ngettext("mail_in_ui_folder_move_target_error",
4764                                                              "mail_in_ui_folder_move_targets_error",
4765                                                              tny_list_get_length (headers)));
4766                 g_object_unref (headers);
4767                 return;
4768         }
4769
4770         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4771         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4772                                                            _CS("ckct_nw_pasting"));
4773         if (helper->banner != NULL)  {
4774                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4775                 gtk_widget_show (GTK_WIDGET(helper->banner));
4776         }
4777
4778         if (MODEST_IS_MAIN_WINDOW (win)) {
4779                 GtkWidget *header_view = 
4780                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4781                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4782                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4783         }
4784
4785         ModestMailOperation *mail_op = 
4786                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4787                                                                modest_ui_actions_move_folder_error_handler,
4788                                                                NULL, NULL);
4789         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4790                                          mail_op);
4791
4792         modest_mail_operation_xfer_msgs (mail_op, 
4793                                          headers,
4794                                          TNY_FOLDER (dst_folder),
4795                                          TRUE,
4796                                          msgs_move_to_cb,
4797                                          helper);
4798
4799         g_object_unref (G_OBJECT (mail_op));
4800         g_object_unref (headers);
4801         g_object_unref (dst_folder);
4802 }
4803
4804 typedef struct {
4805         TnyFolder *src_folder;
4806         TnyFolderStore *dst_folder;
4807         gboolean delete_original;
4808         GtkWidget *folder_view;
4809 } MoveFolderInfo;
4810
4811 static void
4812 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4813                 TnyAccount *account, gpointer user_data)
4814 {
4815         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4816         GtkTreeSelection *sel;
4817         ModestMailOperation *mail_op = NULL;
4818         
4819         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4820                 g_object_unref (G_OBJECT (info->src_folder));
4821                 g_object_unref (G_OBJECT (info->dst_folder));
4822                 g_free (info);
4823                 return;
4824         }
4825         
4826         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4827         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4828                         _CS("ckct_nw_pasting"));
4829         if (helper->banner != NULL)  {
4830                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4831                 gtk_widget_show (GTK_WIDGET(helper->banner));
4832         }
4833         /* Clean folder on header view before moving it */
4834         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4835         gtk_tree_selection_unselect_all (sel);
4836
4837         /* Let gtk events run. We need that the folder
4838            view frees its reference to the source
4839            folder *before* issuing the mail operation
4840            so we need the signal handler of selection
4841            changed to happen before the mail
4842            operation 
4843         while (gtk_events_pending ())
4844                 gtk_main_iteration ();   */
4845
4846         mail_op =
4847                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4848                                 modest_ui_actions_move_folder_error_handler,
4849                                 info->src_folder, NULL);
4850         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4851                         mail_op);
4852
4853         /* Select *after* the changes */
4854         /* TODO: this function hangs UI after transfer */ 
4855         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4856         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4857
4858         modest_mail_operation_xfer_folder (mail_op,
4859                         TNY_FOLDER (info->src_folder),
4860                         info->dst_folder,
4861                         info->delete_original, 
4862                         folder_move_to_cb, 
4863                         helper);
4864
4865         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {       
4866                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4867                                                   TNY_FOLDER (info->dst_folder), TRUE);
4868         }
4869         
4870         /* Unref mail operation */
4871         g_object_unref (G_OBJECT (mail_op));
4872         g_object_unref (G_OBJECT (info->src_folder));
4873         g_object_unref (G_OBJECT (info->dst_folder));
4874         g_free (user_data);
4875 }
4876
4877 static TnyAccount *
4878 get_account_from_folder_store (TnyFolderStore *folder_store) 
4879 {
4880         if (TNY_IS_ACCOUNT (folder_store))
4881                 return g_object_ref (folder_store);
4882         else
4883                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4884 }
4885
4886 /*
4887  * UI handler for the "Move to" action when invoked from the
4888  * ModestMainWindow
4889  */
4890 static void 
4891 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4892                                           GtkWidget *folder_view,
4893                                           TnyFolderStore *dst_folder,
4894                                           ModestMainWindow *win)
4895 {
4896         ModestHeaderView *header_view = NULL;
4897         TnyFolderStore *src_folder = NULL;
4898
4899         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4900
4901         /* Get the source folder */
4902         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4903
4904         /* Get header view */
4905         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4906
4907         /* Get folder or messages to transfer */
4908         if (gtk_widget_is_focus (folder_view)) {
4909                 gboolean do_xfer = TRUE;
4910
4911                 /* Allow only to transfer folders to the local root folder */
4912                 if (TNY_IS_ACCOUNT (dst_folder) && 
4913                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4914                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4915                         do_xfer = FALSE;
4916                 } else if (!TNY_IS_FOLDER (src_folder)) {
4917                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4918                         do_xfer = FALSE;
4919                 }
4920
4921                 if (do_xfer) {                  
4922                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4923                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4924
4925                         info->src_folder = g_object_ref (src_folder);
4926                         info->dst_folder = g_object_ref (dst_folder);
4927                         info->delete_original = TRUE;
4928                         info->folder_view = folder_view;
4929
4930                         connect_info->callback = on_move_folder_cb;
4931                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4932                         connect_info->data = info;
4933
4934                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4935                                                                    TNY_FOLDER_STORE (src_folder), 
4936                                                                    connect_info);
4937                 }
4938         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4939                 TnyList *headers;
4940
4941                 headers = modest_header_view_get_selected_headers(header_view);
4942
4943                 /* Transfer the messages */
4944                 transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
4945                                           headers, TNY_FOLDER (dst_folder));
4946
4947                 g_object_unref (headers);
4948         }
4949
4950         /* Frees */
4951         g_object_unref (src_folder);
4952 }
4953
4954
4955 static void
4956 transfer_messages_helper (GtkWindow *win,
4957                           TnyFolder *src_folder,
4958                           TnyList *headers,
4959                           TnyFolder *dst_folder)
4960 {
4961         gboolean need_connection = TRUE;
4962         gboolean do_xfer = TRUE;
4963         
4964         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
4965                                                headers, TNY_FOLDER (dst_folder),
4966                                                TRUE, &need_connection, 
4967                                                &do_xfer);
4968
4969         /* If we don't want to transfer just return */
4970         if (!do_xfer)
4971                 return;
4972
4973         if (need_connection) {
4974                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4975                 connect_info->callback = xfer_messages_performer;
4976                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4977                 connect_info->data = g_object_ref (dst_folder);
4978                 
4979                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4980                                                            TNY_FOLDER_STORE (src_folder), 
4981                                                            connect_info);
4982         } else {
4983                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
4984                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
4985                                          src_account, 
4986                                          g_object_ref (dst_folder));
4987                 g_object_unref (src_account);
4988         }
4989 }
4990
4991 /*
4992  * UI handler for the "Move to" action when invoked from the
4993  * ModestMsgViewWindow
4994  */
4995 static void 
4996 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4997                                               TnyFolderStore *dst_folder,
4998                                               ModestMsgViewWindow *win)
4999 {
5000         TnyList *headers = NULL;
5001         TnyHeader *header = NULL;
5002         TnyFolder *src_folder = NULL;
5003
5004         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5005
5006         /* Create header list */
5007         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5008         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5009         headers = tny_simple_list_new ();
5010         tny_list_append (headers, G_OBJECT (header));
5011
5012         /* Transfer the messages */
5013         transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5014                                   TNY_FOLDER (dst_folder));
5015
5016         /* Frees */
5017         g_object_unref (header);
5018         g_object_unref (headers);
5019 }
5020
5021 void 
5022 modest_ui_actions_on_move_to (GtkAction *action, 
5023                               ModestWindow *win)
5024 {
5025         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5026         gint result = 0;
5027         TnyFolderStore *dst_folder = NULL;
5028         ModestMainWindow *main_window;
5029
5030         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5031                           MODEST_IS_MSG_VIEW_WINDOW (win));
5032
5033         /* Get the main window if exists */
5034         if (MODEST_IS_MAIN_WINDOW (win))
5035                 main_window = MODEST_MAIN_WINDOW (win);
5036         else
5037                 main_window = 
5038                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5039                                                                                FALSE)); /* don't create */
5040
5041         /* Get the folder view widget if exists */
5042         if (main_window)
5043                 folder_view = modest_main_window_get_child_widget (main_window,
5044                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5045         else
5046                 folder_view = NULL;
5047
5048         /* Create and run the dialog */
5049         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5050         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5051         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5052         result = gtk_dialog_run (GTK_DIALOG(dialog));
5053         g_object_ref (tree_view);
5054         gtk_widget_destroy (dialog);
5055
5056         if (result != GTK_RESPONSE_ACCEPT)
5057                 return;
5058
5059         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5060         /* Do window specific stuff */
5061         if (MODEST_IS_MAIN_WINDOW (win)) {
5062                 modest_ui_actions_on_main_window_move_to (action,
5063                                 folder_view,
5064                                 dst_folder,
5065                                 MODEST_MAIN_WINDOW (win));
5066         } else {
5067                 modest_ui_actions_on_msg_view_window_move_to (action,
5068                                 dst_folder,
5069                                 MODEST_MSG_VIEW_WINDOW (win));
5070         }
5071
5072         if (dst_folder)
5073                 g_object_unref (dst_folder);
5074 }
5075
5076 /*
5077  * Calls #HeadersFunc for each header already selected in the main
5078  * window or the message currently being shown in the msg view window
5079  */
5080 static void
5081 do_headers_action (ModestWindow *win, 
5082                    HeadersFunc func,
5083                    gpointer user_data)
5084 {
5085         TnyList *headers_list = NULL;
5086         TnyIterator *iter = NULL;
5087         TnyHeader *header = NULL;
5088         TnyFolder *folder = NULL;
5089
5090         /* Get headers */
5091         headers_list = get_selected_headers (win);
5092         if (!headers_list)
5093                 return;
5094
5095         /* Get the folder */
5096         iter = tny_list_create_iterator (headers_list);
5097         header = TNY_HEADER (tny_iterator_get_current (iter));
5098         if (header) {
5099                 folder = tny_header_get_folder (header);
5100                 g_object_unref (header);
5101         }
5102
5103         /* Call the function for each header */
5104         while (!tny_iterator_is_done (iter)) {
5105                 header = TNY_HEADER (tny_iterator_get_current (iter));
5106                 func (header, win, user_data);
5107                 g_object_unref (header);
5108                 tny_iterator_next (iter);
5109         }
5110
5111         /* Trick: do a poke status in order to speed up the signaling
5112            of observers */
5113         tny_folder_poke_status (folder);
5114
5115         /* Frees */
5116         g_object_unref (folder);
5117         g_object_unref (iter);
5118         g_object_unref (headers_list);
5119 }
5120
5121 void 
5122 modest_ui_actions_view_attachment (GtkAction *action,
5123                                    ModestWindow *window)
5124 {
5125         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5126                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5127         } else {
5128                 /* not supported window for this action */
5129                 g_return_if_reached ();
5130         }
5131 }
5132
5133 void
5134 modest_ui_actions_save_attachments (GtkAction *action,
5135                                     ModestWindow *window)
5136 {
5137         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5138                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5139         } else {
5140                 /* not supported window for this action */
5141                 g_return_if_reached ();
5142         }
5143 }
5144
5145 void
5146 modest_ui_actions_remove_attachments (GtkAction *action,
5147                                       ModestWindow *window)
5148 {
5149         if (MODEST_IS_MAIN_WINDOW (window)) {
5150                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5151         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5152                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5153         } else {
5154                 /* not supported window for this action */
5155                 g_return_if_reached ();
5156         }
5157 }
5158
5159 void 
5160 modest_ui_actions_on_settings (GtkAction *action, 
5161                                ModestWindow *win)
5162 {
5163         GtkWidget *dialog;
5164
5165         dialog = modest_platform_get_global_settings_dialog ();
5166         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5167         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5168         gtk_widget_show_all (dialog);
5169
5170         gtk_dialog_run (GTK_DIALOG (dialog));
5171
5172         gtk_widget_destroy (dialog);
5173 }
5174
5175 void 
5176 modest_ui_actions_on_help (GtkAction *action, 
5177                            GtkWindow *win)
5178 {
5179         const gchar *help_id;
5180
5181         g_return_if_fail (action);
5182         g_return_if_fail (win && GTK_IS_WINDOW(win));
5183         
5184         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5185         
5186         if (help_id)
5187                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5188         else
5189                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5190 }
5191
5192 static void
5193 retrieve_msg_contents_performer (gboolean canceled, 
5194                                  GError *err,
5195                                  GtkWindow *parent_window, 
5196                                  TnyAccount *account, 
5197                                  gpointer user_data)
5198 {
5199         ModestMailOperation *mail_op;
5200         TnyList *headers = TNY_LIST (user_data);
5201
5202         if (err || canceled) {
5203                 goto out;
5204         }
5205
5206         /* Create mail operation */
5207         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5208                                                                  modest_ui_actions_get_msgs_full_error_handler, 
5209                                                                  NULL, NULL);
5210         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5211         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5212
5213         /* Frees */
5214         g_object_unref (mail_op);
5215  out:
5216         g_object_unref (headers);
5217         g_object_unref (account);
5218 }
5219
5220 void 
5221 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5222                                             ModestWindow *window)
5223 {
5224         TnyList *headers = NULL;
5225         TnyAccount *account = NULL;
5226         TnyIterator *iter = NULL;
5227         TnyHeader *header = NULL;
5228         TnyFolder *folder = NULL;
5229
5230         /* Get headers */
5231         headers = get_selected_headers (window);
5232         if (!headers)
5233                 return;
5234
5235         /* Pick the account */
5236         iter = tny_list_create_iterator (headers);
5237         header = TNY_HEADER (tny_iterator_get_current (iter));
5238         folder = tny_header_get_folder (header);
5239         account = tny_folder_get_account (folder);
5240         g_object_unref (folder);
5241         g_object_unref (header);
5242         g_object_unref (iter);
5243
5244         /* Connect and perform the message retrieval */
5245         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5246                                              g_object_ref (account), 
5247                                              retrieve_msg_contents_performer, 
5248                                              g_object_ref (headers));
5249
5250         /* Frees */
5251         g_object_unref (account);
5252         g_object_unref (headers);
5253 }
5254
5255 void
5256 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5257 {
5258         g_return_if_fail (MODEST_IS_WINDOW (window));
5259
5260         /* Update dimmed */
5261         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5262 }
5263
5264 void
5265 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5266 {
5267         g_return_if_fail (MODEST_IS_WINDOW (window));
5268
5269         /* Update dimmed */
5270         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5271 }
5272
5273 void
5274 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5275                                           ModestWindow *window)
5276 {
5277         g_return_if_fail (MODEST_IS_WINDOW (window));
5278         
5279         /* Update dimmed */
5280         modest_ui_actions_check_menu_dimming_rules (window);
5281 }
5282
5283 void
5284 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5285                                           ModestWindow *window)
5286 {
5287         g_return_if_fail (MODEST_IS_WINDOW (window));
5288
5289         /* Update dimmed */
5290         modest_ui_actions_check_menu_dimming_rules (window);
5291 }
5292
5293 void
5294 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5295                                           ModestWindow *window)
5296 {
5297         g_return_if_fail (MODEST_IS_WINDOW (window));
5298
5299         /* Update dimmed */
5300         modest_ui_actions_check_menu_dimming_rules (window);
5301 }
5302
5303 void
5304 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5305                                             ModestWindow *window)
5306 {
5307         g_return_if_fail (MODEST_IS_WINDOW (window));
5308
5309         /* Update dimmed */
5310         modest_ui_actions_check_menu_dimming_rules (window);
5311 }
5312
5313 void
5314 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5315                                           ModestWindow *window)
5316 {
5317         g_return_if_fail (MODEST_IS_WINDOW (window));
5318
5319         /* Update dimmed */
5320         modest_ui_actions_check_menu_dimming_rules (window);
5321 }
5322
5323 void
5324 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5325                                           ModestWindow *window)
5326 {
5327         g_return_if_fail (MODEST_IS_WINDOW (window));
5328
5329         /* Update dimmed */
5330         modest_ui_actions_check_menu_dimming_rules (window);
5331 }
5332
5333 void
5334 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5335                                                  ModestWindow *window)
5336 {
5337         g_return_if_fail (MODEST_IS_WINDOW (window));
5338
5339         /* Update dimmed */
5340         modest_ui_actions_check_menu_dimming_rules (window);
5341 }
5342
5343 void
5344 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5345                                                      ModestWindow *window)
5346 {
5347         g_return_if_fail (MODEST_IS_WINDOW (window));
5348
5349         /* Update dimmed */
5350         modest_ui_actions_check_menu_dimming_rules (window);
5351 }
5352
5353 void
5354 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5355                                                      ModestWindow *window)
5356 {
5357         g_return_if_fail (MODEST_IS_WINDOW (window));
5358
5359         /* Update dimmed */
5360         modest_ui_actions_check_menu_dimming_rules (window);
5361 }
5362
5363 void
5364 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5365 {
5366         g_return_if_fail (MODEST_IS_WINDOW (window));
5367
5368         modest_platform_show_search_messages (GTK_WINDOW (window));
5369 }
5370
5371 void     
5372 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5373 {
5374         g_return_if_fail (MODEST_IS_WINDOW (win));
5375         modest_platform_show_addressbook (GTK_WINDOW (win));
5376 }
5377
5378
5379 void
5380 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5381                                           ModestWindow *window)
5382 {
5383         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5384
5385         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5386 }
5387
5388 static void 
5389 on_send_receive_finished (ModestMailOperation  *mail_op, 
5390                            gpointer user_data)
5391 {
5392         GtkWidget *header_view, *folder_view;
5393         TnyFolderStore *folder_store;
5394         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5395
5396         /* Set send/receive operation finished */       
5397         modest_main_window_notify_send_receive_completed (main_win);
5398
5399         /* Don't refresh the current folder if there were any errors */
5400         if (modest_mail_operation_get_status (mail_op) !=
5401             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5402                 return;
5403         
5404         /* Refresh the current folder if we're viewing a window. We do
5405            this because the user won't be able to see the new mails in
5406            the selected folder after a Send&Receive because it only
5407            performs a poke_status, i.e, only the number of read/unread
5408            messages is updated, but the new headers are not
5409            downloaded */
5410         folder_view = modest_main_window_get_child_widget (main_win, 
5411                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5412         if (!folder_view)
5413                 return;
5414
5415         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5416         
5417         /* Do not need to refresh INBOX again because the
5418            update_account does it always automatically */
5419         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5420             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5421                 ModestMailOperation *refresh_op;
5422
5423                 header_view = modest_main_window_get_child_widget (main_win,
5424                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5425                 
5426                 /* We do not need to set the contents style
5427                    because it hasn't changed. We also do not
5428                    need to save the widget status. Just force
5429                    a refresh */
5430                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5431                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5432                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5433                                                       folder_refreshed_cb, main_win);
5434                 g_object_unref (refresh_op);
5435         }
5436         
5437         if (folder_store)
5438                 g_object_unref (folder_store);
5439 }
5440
5441
5442 void 
5443 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5444                                                 TnyHeader *header, 
5445                                                 TnyMsg *msg, 
5446                                                 GError *err, 
5447                                                 gpointer user_data)
5448 {
5449         const gchar* server_name = NULL;
5450         TnyTransportAccount *server_account;
5451         gchar *message = NULL;
5452
5453         /* Don't show anything if the user cancelled something */
5454         if (err->code == TNY_SYSTEM_ERROR_CANCEL)
5455                 return;
5456
5457         /* Get the server name: */
5458         server_account = 
5459                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5460         if (server_account) {
5461                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5462                         
5463                 g_object_unref (server_account);
5464                 server_account = NULL;
5465         }
5466         
5467         g_return_if_fail (server_name);
5468
5469         /* Show the appropriate message text for the GError: */
5470         switch (err->code) {
5471         case TNY_SERVICE_ERROR_CONNECT:
5472                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5473                 break;
5474         case TNY_SERVICE_ERROR_AUTHENTICATE:
5475                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5476                 break;
5477         case TNY_SERVICE_ERROR_SEND:
5478                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5479                 break;
5480         case TNY_SERVICE_ERROR_UNAVAILABLE:
5481                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5482                 break;
5483         default:
5484                 g_warning ("%s: unexpected ERROR %d",
5485                            __FUNCTION__, err->code);
5486                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5487                 break;  
5488         }
5489         
5490         /* TODO if the username or the password where not defined we
5491            should show the Accounts Settings dialog or the Connection
5492            specific SMTP server window */
5493
5494         modest_platform_run_information_dialog (NULL, message);
5495         g_free (message);
5496 }
5497
5498 void
5499 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5500                                                 gchar *msg_id, 
5501                                                 guint status,
5502                                                 gpointer user_data)
5503 {
5504         ModestMainWindow *main_window = NULL;
5505         ModestWindowMgr *mgr = NULL;
5506         GtkWidget *folder_view = NULL, *header_view = NULL;
5507         TnyFolderStore *selected_folder = NULL;
5508         TnyFolderType folder_type;
5509
5510         mgr = modest_runtime_get_window_mgr ();
5511         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5512                                                                              FALSE));/* don't create */
5513         if (!main_window)
5514                 return;
5515
5516         /* Check if selected folder is OUTBOX */
5517         folder_view = modest_main_window_get_child_widget (main_window,
5518                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5519         header_view = modest_main_window_get_child_widget (main_window,
5520                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5521
5522         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5523         if (!TNY_IS_FOLDER (selected_folder)) 
5524                 goto frees;
5525
5526         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5527 #if GTK_CHECK_VERSION(2, 8, 0) 
5528         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5529         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5530                 GtkTreeViewColumn *tree_column;
5531
5532                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5533                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5534                 gtk_tree_view_column_queue_resize (tree_column);
5535         }
5536 #else
5537         gtk_widget_queue_draw (header_view);
5538 #endif          
5539
5540         /* Rerun dimming rules, because the message could become deletable for example */
5541         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5542                                                  MODEST_DIMMING_RULES_TOOLBAR);
5543         
5544         /* Free */
5545  frees:
5546         if (selected_folder != NULL)
5547                 g_object_unref (selected_folder);
5548 }
5549
5550 void 
5551 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5552                                                TnyAccount *account)
5553 {
5554         ModestTransportStoreProtocol proto;
5555         const gchar *proto_name;
5556         gchar *error_note = NULL;
5557         
5558         proto_name = tny_account_get_proto (account);
5559         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5560         
5561         switch (proto) {
5562         case MODEST_PROTOCOL_STORE_POP:
5563                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5564                                               tny_account_get_hostname (account));
5565                 break;
5566         case MODEST_PROTOCOL_STORE_IMAP:
5567                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5568                                               tny_account_get_hostname (account));
5569                 break;
5570         case MODEST_PROTOCOL_STORE_MAILDIR:
5571         case MODEST_PROTOCOL_STORE_MBOX:
5572                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5573                 break;
5574         default:
5575                 g_warning ("%s: This should not be reached", __FUNCTION__);
5576         }
5577
5578         if (error_note) {
5579                 modest_platform_run_information_dialog (parent_window, error_note);
5580                 g_free (error_note);
5581         }
5582 }
5583
5584 gchar *
5585 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5586 {
5587         gchar *msg = NULL;
5588         TnyFolderStore *folder = NULL;
5589         TnyAccount *account = NULL;
5590         ModestTransportStoreProtocol proto;
5591         TnyHeader *header = NULL;
5592
5593         if (MODEST_IS_MAIN_WINDOW (win)) {
5594                 GtkWidget *header_view;
5595                 TnyList* headers = NULL;
5596                 TnyIterator *iter;
5597                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5598                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5599                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5600                 if (!headers || tny_list_get_length (headers) == 0) {
5601                         if (headers)
5602                                 g_object_unref (headers);
5603                         return NULL;
5604                 }
5605                 iter = tny_list_create_iterator (headers);
5606                 header = TNY_HEADER (tny_iterator_get_current (iter));
5607                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5608                 g_object_unref (iter);
5609                 g_object_unref (headers);
5610         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5611                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5612                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5613         }
5614
5615         /* Get the account type */
5616         account = tny_folder_get_account (TNY_FOLDER (folder));
5617         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5618         if (proto == MODEST_PROTOCOL_STORE_POP) {
5619                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5620         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5621                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
5622                                        tny_header_get_subject (header));
5623         } else {
5624                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5625         }
5626
5627         /* Frees */
5628         g_object_unref (account);
5629         g_object_unref (folder);
5630         g_object_unref (header);
5631
5632         return msg;
5633 }