* Define a new mail-operation to remove several messages.
[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
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _PasteAsAttachmentHelper {
107         ModestMsgEditWindow *window;
108         GtkWidget *banner;
109 } PasteAsAttachmentHelper;
110
111
112 /*
113  * The do_headers_action uses this kind of functions to perform some
114  * action to each member of a list of headers
115  */
116 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
117
118 static void     do_headers_action     (ModestWindow *win, 
119                                        HeadersFunc func,
120                                        gpointer user_data);
121
122 static void     open_msg_cb            (ModestMailOperation *mail_op, 
123                                         TnyHeader *header, 
124                                         TnyMsg *msg,
125                                         gpointer user_data);
126
127 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
133
134 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
135                                         TnyFolder *folder, 
136                                         gpointer user_data);
137
138 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
139                                                    ModestMailOperationState *state,
140                                                    gpointer user_data);
141
142 static gboolean download_uncached_messages (TnyList *header_list, 
143                                             GtkWindow *win);
144
145
146
147 /* Show the account creation wizard dialog.
148  * returns: TRUE if an account was created. FALSE if the user cancelled.
149  */
150 gboolean
151 modest_run_account_setup_wizard (ModestWindow *win)
152 {
153         gboolean result = FALSE;
154         GtkDialog *wizard;
155         
156         wizard = modest_window_mgr_get_easysetup_dialog
157                 (modest_runtime_get_window_mgr());
158         if (wizard) {
159                 /* old wizard is active already; present it and
160                  * act as if the user cancelled the non-existing
161                  * new one
162                  */
163                 printf ("wizard already active\n");
164                 return FALSE;
165         } else {
166                 /* there is no such wizard yet */
167                 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
168                 modest_window_mgr_set_easysetup_dialog
169                         (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
170         } 
171
172         
173         /* always present a main window in the background 
174          * we do it here, so we cannot end up with to wizards (as this
175          * function might be called in modest_window_mgr_get_main_window as well */
176         if (!win) 
177                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
178
179         /* make sure the mainwindow is visible */
180         gtk_widget_show_all (GTK_WIDGET(win));
181         gtk_window_present (GTK_WINDOW(win));
182
183         
184         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
185
186         /* Don't make this a modal window, because secondary windows will then 
187          * be unusable, freezing the UI: */
188         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
189         
190         gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
191         if (dialog_response == GTK_RESPONSE_CANCEL)
192                 result = FALSE;
193         else {
194                 /* Check whether an account was created: */
195                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
196         }
197         
198         gtk_widget_destroy (GTK_WIDGET (wizard));
199
200         /* clear it from the window mgr */
201         modest_window_mgr_set_easysetup_dialog
202                 (modest_runtime_get_window_mgr(), NULL);
203         
204         return result;
205 }
206
207
208 void   
209 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
210 {
211         GtkWidget *about;
212         const gchar *authors[] = {
213                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
214                 NULL
215         };
216         about = gtk_about_dialog_new ();
217         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
218         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
219         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
220                                         _("Copyright (c) 2006, Nokia Corporation\n"
221                                           "All rights reserved."));
222         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
223                                        _("a modest e-mail client\n\n"
224                                          "design and implementation: Dirk-Jan C. Binnema\n"
225                                          "contributions from the fine people at KC and Ig\n"
226                                          "uses the tinymail email framework written by Philip van Hoof"));
227         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
228         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
229         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
230         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
231         
232         gtk_dialog_run (GTK_DIALOG (about));
233         gtk_widget_destroy(about);
234 }
235
236 /*
237  * Gets the list of currently selected messages. If the win is the
238  * main window, then it returns a newly allocated list of the headers
239  * selected in the header view. If win is the msg view window, then
240  * the value returned is a list with just a single header.
241  *
242  * The caller of this funcion must free the list.
243  */
244 static TnyList *
245 get_selected_headers (ModestWindow *win)
246 {
247         if (MODEST_IS_MAIN_WINDOW(win)) {
248                 GtkWidget *header_view;         
249                 
250                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
251                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
252                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
253                 
254         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
255                 /* for MsgViewWindows, we simply return a list with one element */
256                 TnyHeader *header;
257                 TnyList *list = NULL;
258                 
259                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
260                 if (header != NULL) {
261                         list = tny_simple_list_new ();
262                         tny_list_prepend (list, G_OBJECT(header));
263                         g_object_unref (G_OBJECT(header));
264                 }
265
266                 return list;
267
268         } else
269                 return NULL;
270 }
271
272 static void
273 headers_action_mark_as_read (TnyHeader *header,
274                              ModestWindow *win,
275                              gpointer user_data)
276 {
277         TnyHeaderFlags flags;
278
279         g_return_if_fail (TNY_IS_HEADER(header));
280
281         flags = tny_header_get_flags (header);
282         if (flags & TNY_HEADER_FLAG_SEEN) return;
283         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
284 }
285
286 static void
287 headers_action_mark_as_unread (TnyHeader *header,
288                                ModestWindow *win,
289                                gpointer user_data)
290 {
291         TnyHeaderFlags flags;
292
293         g_return_if_fail (TNY_IS_HEADER(header));
294
295         flags = tny_header_get_flags (header);
296         if (flags & TNY_HEADER_FLAG_SEEN)  {
297                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
298         }
299 }
300
301 /** A convenience method, because deleting a message is 
302  * otherwise complicated, and it's best to change it in one place 
303  * when we change it.
304  */
305 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
306 {
307         ModestMailOperation *mail_op = NULL;
308         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
309                 win ? G_OBJECT(win) : NULL);
310         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
311                                          mail_op);
312         
313         /* Always delete. TODO: Move to trash still not supported */
314         modest_mail_operation_remove_msg (mail_op, header, FALSE);
315         g_object_unref (G_OBJECT (mail_op));
316 }
317
318 /** A convenience method, because deleting a message is 
319  * otherwise complicated, and it's best to change it in one place 
320  * when we change it.
321  */
322 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
323 {
324         ModestMailOperation *mail_op = NULL;
325         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
326                 win ? G_OBJECT(win) : NULL);
327         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
328                                          mail_op);
329         
330         /* Always delete. TODO: Move to trash still not supported */
331         modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
332         g_object_unref (G_OBJECT (mail_op));
333 }
334
335 /* static void */
336 /* headers_action_delete (TnyHeader *header, */
337 /*                     ModestWindow *win, */
338 /*                     gpointer user_data) */
339 /* { */
340 /*      modest_do_message_delete (header, win); */
341
342 /* } */
343
344 /** After deleing a message that is currently visible in a window, 
345  * show the next message from the list, or close the window if there are no more messages.
346  **/
347 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
348 {
349         /* Close msg view window or select next */
350         if (modest_msg_view_window_last_message_selected (win) &&
351                 modest_msg_view_window_first_message_selected (win)) {
352                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
353         } else {
354                 if (!modest_msg_view_window_select_next_message (win)) {
355                         gboolean ret_value;
356                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
357                 }
358         }
359 }
360
361 void
362 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
363 {
364         TnyList *header_list = NULL;
365         TnyIterator *iter = NULL;
366         TnyHeader *header = NULL;
367         gchar *message = NULL;
368         gchar *desc = NULL;
369         gint response;
370         ModestWindowMgr *mgr;
371         GtkWidget *header_view = NULL;
372
373         g_return_if_fail (MODEST_IS_WINDOW(win));
374         
375         /* Check first if the header view has the focus */
376         if (MODEST_IS_MAIN_WINDOW (win)) {
377                 header_view = 
378                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
379                                                              MODEST_WIDGET_TYPE_HEADER_VIEW);
380                 if (!gtk_widget_is_focus (header_view))
381                         return;
382         }
383         
384         /* Get the headers, either from the header view (if win is the main window),
385          * or from the message view window: */
386         header_list = get_selected_headers (win);
387         if (!header_list) return;
388                         
389         /* Check if any of the headers are already opened, or in the process of being opened */
390         if (MODEST_IS_MAIN_WINDOW (win)) {
391                 gboolean found;
392                 iter = tny_list_create_iterator (header_list);
393                 found = FALSE;
394                 mgr = modest_runtime_get_window_mgr ();
395                 while (!tny_iterator_is_done (iter) && !found) {
396                         header = TNY_HEADER (tny_iterator_get_current (iter));
397                         if (header) {
398                                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
399                                 g_object_unref (header);
400                         }
401
402                         tny_iterator_next (iter);
403                 }
404                 g_object_unref (iter);
405
406                 if (found) {
407                         gchar *num, *msg;
408
409                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
410                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
411
412                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
413                         
414                         g_free (msg);
415                         g_free (num);
416                         g_object_unref (header_list);
417                         return;
418                 }
419         }
420
421         /* Select message */
422         if (tny_list_get_length(header_list) == 1) {
423                 iter = tny_list_create_iterator (header_list);
424                 header = TNY_HEADER (tny_iterator_get_current (iter));
425                 if (header) {
426                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
427                         g_object_unref (header);
428                 }
429
430                 g_object_unref (iter);
431         }
432         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
433                                            tny_list_get_length(header_list)), desc);
434
435         /* Confirmation dialog */
436         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
437                                                             message);
438         
439
440         if (response == GTK_RESPONSE_OK) {      
441                 ModestWindow *main_window = NULL;
442                 ModestWindowMgr *mgr = NULL;
443                 GtkTreeModel *model = NULL;
444                 GtkTreeSelection *sel = NULL;
445                 GList *sel_list = NULL, *tmp = NULL;
446                 GtkTreeRowReference *row_reference = NULL;
447                 GtkTreePath *next_path = NULL;
448                 GError *err = NULL;
449
450                 /* Find last selected row */                    
451                 if (MODEST_IS_MAIN_WINDOW (win)) {
452                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
453                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
454                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
455                         for (tmp=sel_list; tmp; tmp=tmp->next) {
456                                 if (tmp->next == NULL) {
457                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
458                                         gtk_tree_path_next (next_path);
459                                         row_reference = gtk_tree_row_reference_new (model, next_path);
460                                         gtk_tree_path_free (next_path);
461                                 }
462                         }
463                 }
464                 
465                 /* Disable window dimming management */
466                 modest_window_disable_dimming (MODEST_WINDOW(win));
467
468                 /* Remove each header. If it's a view window header_view == NULL */
469 /*              do_headers_action (win, headers_action_delete, header_view); */
470                 modest_do_messages_delete (header_list, win);
471                 
472
473                 /* Enable window dimming management */
474                 gtk_tree_selection_unselect_all (sel);
475                 modest_window_enable_dimming (MODEST_WINDOW(win));
476
477                 /* FIXME: May be folder_monitor will also refilter treemode on EXPUNGE changes ? */
478                 /* refresh the header view (removing marked-as-deleted) */
479 /*              modest_header_view_refilter (MODEST_HEADER_VIEW(header_view));  */
480                 
481                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
482                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
483                         
484                         /* Get main window */
485                         mgr = modest_runtime_get_window_mgr ();
486                         main_window = modest_window_mgr_get_main_window (mgr);
487                 }
488                 else {                  
489                         /* Move cursor to next row */
490                         main_window = win; 
491
492                         /* Select next row */
493                         if (gtk_tree_row_reference_valid (row_reference)) {
494                                 next_path = gtk_tree_row_reference_get_path (row_reference);
495                                 gtk_tree_selection_select_path (sel, next_path);
496                                 gtk_tree_path_free (next_path);
497                         }
498                         if (row_reference != NULL)
499                                 gtk_tree_row_reference_free (row_reference);
500                 }
501
502                 if (err != NULL) {
503                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
504                         g_error_free(err);
505                 }
506                 
507                 /* Update toolbar dimming state */
508                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
509
510                 /* Free */
511                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
512                 g_list_free (sel_list);
513         }
514
515         /* Free*/
516         g_free(message);
517         g_free(desc);
518         g_object_unref (header_list);
519 }
520
521
522
523
524 /* delete either message or folder, based on where we are */
525 void
526 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
527 {
528         g_return_if_fail (MODEST_IS_WINDOW(win));
529         
530         /* Check first if the header view has the focus */
531         if (MODEST_IS_MAIN_WINDOW (win)) {
532                 GtkWidget *w;
533                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
534                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
535                 if (gtk_widget_is_focus (w)) {
536                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
537                         return;
538                 }
539         }
540         modest_ui_actions_on_delete_message (action, win);
541 }
542
543
544
545 void
546 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
547 {
548 #ifdef MODEST_PLATFORM_MAEMO
549         modest_osso_save_state();
550 #endif /* MODEST_PLATFORM_MAEMO */
551
552         g_debug ("closing down, clearing %d item(s) from operation queue",
553                  modest_mail_operation_queue_num_elements
554                  (modest_runtime_get_mail_operation_queue()));
555
556         /* cancel all outstanding operations */
557         modest_mail_operation_queue_cancel_all 
558                 (modest_runtime_get_mail_operation_queue());
559         
560         g_debug ("queue has been cleared");
561
562         /* note: when modest-tny-account-store is finalized,
563            it will automatically set all network connections
564            to offline */
565
566         gtk_main_quit ();
567 }
568
569 void
570 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
571 {
572         gboolean ret_value;
573
574         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
575
576 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
577 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
578 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
579 /*              gboolean ret_value; */
580 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
581 /*      } else if (MODEST_IS_WINDOW (win)) { */
582 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
583 /*      } else { */
584 /*              g_return_if_reached (); */
585 /*      } */
586 }
587
588 void
589 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
590 {
591         GtkClipboard *clipboard = NULL;
592         gchar *selection = NULL;
593
594         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
595         selection = gtk_clipboard_wait_for_text (clipboard);
596
597         /* Question: why is the clipboard being used here? 
598          * It doesn't really make a lot of sense. */
599
600         if (selection)
601         {
602                 modest_address_book_add_address (selection);
603                 g_free (selection);
604         }
605 }
606
607 void
608 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
609 {
610         /* This is currently only implemented for Maemo */
611 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
612         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
613                 modest_run_account_setup_wizard (win);
614                 return;
615         } else  {
616                 /* Show the list of accounts: */
617                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
618                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
619                 
620                 /* Don't make this a modal window, because secondary windows will then 
621                  * be unusable, freezing the UI: */
622                 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
623                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
624         }
625 #else
626         GtkWidget *dialog, *label;
627         
628         /* Create the widgets */
629         
630         dialog = gtk_dialog_new_with_buttons ("Message",
631                                               GTK_WINDOW(win),
632                                               GTK_DIALOG_DESTROY_WITH_PARENT,
633                                               GTK_STOCK_OK,
634                                               GTK_RESPONSE_NONE,
635                                               NULL);
636         label = gtk_label_new ("Hello World!");
637         
638         /* Ensure that the dialog box is destroyed when the user responds. */
639         
640         g_signal_connect_swapped (dialog, "response", 
641                                   G_CALLBACK (gtk_widget_destroy),
642                                   dialog);
643         
644         /* Add the label, and show everything we've added to the dialog. */
645         
646         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
647                            label);
648         gtk_widget_show_all (dialog);
649 #endif /* MODEST_PLATFORM_MAEMO */
650 }
651
652 static void
653 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
654 {
655         ModestWindow *main_window = MODEST_WINDOW (user_data);
656         
657         /* Save any changes. */
658         modest_connection_specific_smtp_window_save_server_accounts (
659                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
660                         modest_window_get_active_account (main_window));
661         gtk_widget_destroy (GTK_WIDGET (window));
662 }
663
664
665
666 void
667 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
668 {
669         /* This is currently only implemented for Maemo,
670          * because it requires an API (libconic) to detect different connection 
671          * possiblities.
672          */
673 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
674         
675         /* Create the window if necessary: */
676         const gchar *active_account_name = modest_window_get_active_account (win);
677         
678         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
679          * or show the default account?
680          * If we show the default account then the account name should be shown in 
681          * the window when we show it. */
682         if (!active_account_name) {
683                 g_warning ("%s: No account is active.", __FUNCTION__);
684                 return;
685         }
686                 
687         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
688         modest_connection_specific_smtp_window_fill_with_connections (
689                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
690                 modest_runtime_get_account_mgr(), 
691                 active_account_name);
692
693         /* Show the window: */  
694         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
695         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
696         gtk_widget_show (specific_window);
697     
698         /* Save changes when the window is hidden: */
699         g_signal_connect (specific_window, "hide", 
700                 G_CALLBACK (on_smtp_servers_window_hide), win);
701 #endif /* MODEST_PLATFORM_MAEMO */
702 }
703
704 void
705 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
706 {
707         ModestWindow *msg_win = NULL;
708         TnyMsg *msg = NULL;
709         TnyFolder *folder = NULL;
710         gchar *account_name = NULL;
711         gchar *from_str = NULL;
712 /*      GError *err = NULL; */
713         TnyAccount *account = NULL;
714         ModestWindowMgr *mgr;
715         gchar *signature = NULL, *blank_and_signature = NULL;
716
717         /* if there are no accounts yet, just show the wizard */
718         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
719                         const gboolean created = modest_run_account_setup_wizard (win);
720                         if (!created)
721                                 return;
722         }
723         
724         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
725         if (!account_name)
726                 account_name = g_strdup (modest_window_get_active_account (win));
727         if (!account_name) {
728                 g_printerr ("modest: no account found\n");
729                 goto cleanup;
730         }
731         
732         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
733                                                                        account_name,
734                                                                        TNY_ACCOUNT_TYPE_STORE);
735         if (!account) {
736                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
737                 goto cleanup;
738         }
739
740         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
741         if (!from_str) {
742                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
743                 goto cleanup;
744         }
745
746         gboolean use_signature = FALSE;
747         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
748
749         if (use_signature) {
750                 blank_and_signature = g_strconcat ("\n", signature, NULL);
751         } else {
752                 blank_and_signature = g_strdup ("");
753         }
754
755         g_free (signature);
756
757         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
758         if (!msg) {
759                 g_printerr ("modest: failed to create new msg\n");
760                 goto cleanup;
761         }
762         
763         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
764         if (!folder) {
765                 g_printerr ("modest: failed to find Drafts folder\n");
766                 goto cleanup;
767         }
768         
769
770         /* Create and register edit window */
771         /* This is destroyed by TODO. */
772         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
773         mgr = modest_runtime_get_window_mgr ();
774         modest_window_mgr_register_window (mgr, msg_win);
775
776         if (win)
777                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
778                                               GTK_WINDOW (win));        
779         gtk_widget_show_all (GTK_WIDGET (msg_win));
780
781 cleanup:
782         g_free (account_name);
783         g_free (from_str);
784         g_free (blank_and_signature);
785         if (msg_win)
786                 g_object_unref (msg_win);
787         if (account)
788                 g_object_unref (G_OBJECT(account));
789         if (msg)
790                 g_object_unref (G_OBJECT(msg));
791         if (folder)
792                 g_object_unref (G_OBJECT(folder));
793 }
794
795 gboolean 
796 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
797                                        TnyHeader *header,
798                                        TnyMsg *msg)
799 {
800         ModestMailOperationStatus status;
801
802         /* If there is no message or the operation was not successful */
803         status = modest_mail_operation_get_status (mail_op);
804         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
805
806                 /* Remove the header from the preregistered uids */
807                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
808                                                      header);
809
810                 return FALSE;
811         }
812
813         return TRUE;
814 }
815
816 static void
817 open_msg_cb (ModestMailOperation *mail_op, 
818              TnyHeader *header, 
819              TnyMsg *msg, 
820              gpointer user_data)
821 {
822         ModestWindowMgr *mgr = NULL;
823         ModestWindow *parent_win = NULL;
824         ModestWindow *win = NULL;
825         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
826         gchar *account = NULL;
827         TnyFolder *folder;
828         
829         /* Do nothing if there was any problem with the mail
830            operation. The error will be shown by the error_handler of
831            the mail operation */
832         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
833                 return;
834         }
835
836         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
837         folder = tny_header_get_folder (header);
838
839         /* Mark header as read */
840         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
841
842         /* Get account */
843         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
844         if (!account)
845                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
846         
847         /* Gets folder type (OUTBOX headers will be opened in edit window */
848         if (modest_tny_folder_is_local_folder (folder))
849                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
850
851         /* If the header is in the drafts folder then open the editor,
852            else the message view window */
853         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
854             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
855                 /* we cannot edit without a valid account... */
856                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
857                         const gboolean created = modest_run_account_setup_wizard(parent_win);
858                         if (!created)
859                                 goto cleanup;
860                 }
861                 win = modest_msg_edit_window_new (msg, account, TRUE);
862                 
863         } else {
864                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
865                 
866                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
867                         GtkWidget *header_view;
868                         GtkTreeSelection *sel;
869                         GList *sel_list = NULL;
870                         GtkTreeModel *model;
871                         
872                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
873                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
874
875                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
876                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
877
878                         if (sel_list != NULL) {
879                                 GtkTreeRowReference *row_reference;
880
881                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
882                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
883                                 g_list_free (sel_list);
884                                 
885                                 win = modest_msg_view_window_new_with_header_model (
886                                                 msg, account, (const gchar*) uid,
887                                                 model, row_reference);
888                                 gtk_tree_row_reference_free (row_reference);
889                         } else {
890                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
891                         }
892                 } else {
893                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
894                 }
895                 g_free (uid);
896         }
897         
898         /* Register and show new window */
899         if (win != NULL) {
900                 mgr = modest_runtime_get_window_mgr ();
901                 modest_window_mgr_register_window (mgr, win);
902                 g_object_unref (win);
903                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
904                 gtk_widget_show_all (GTK_WIDGET(win));
905         }
906
907         /* Update toolbar dimming state */
908         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
909                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
910         }
911
912 cleanup:
913         /* Free */
914         g_free(account);
915         g_object_unref (parent_win);
916         g_object_unref (folder);
917 }
918
919 void
920 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
921                                                gpointer user_data)
922 {
923         const GError *error;
924         GObject *win = modest_mail_operation_get_source (mail_op);
925
926         error = modest_mail_operation_get_error (mail_op);
927         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
928  
929         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
930
931                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
932                                                         error->message);
933         } else {
934                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
935                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
936         }
937
938         if (win)
939                 g_object_unref (win);
940 }
941
942 /*
943  * This function is used by both modest_ui_actions_on_open and
944  * modest_ui_actions_on_header_activated. This way we always do the
945  * same when trying to open messages.
946  */
947 static void
948 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
949 {
950         ModestWindowMgr *mgr = NULL;
951         TnyIterator *iter = NULL;
952         ModestMailOperation *mail_op = NULL;
953         TnyList *not_opened_headers = NULL;
954         TnyHeaderFlags flags = 0;
955                 
956         g_return_if_fail (headers != NULL);
957
958         /* Check that only one message is selected for opening */
959         if (tny_list_get_length (headers) != 1) {
960                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
961                                                         _("mcen_ib_select_one_message"));
962                 return;
963         }
964
965
966         /* Look if we already have a message view for each header. If
967            true, then remove the header from the list of headers to
968            open */
969         mgr = modest_runtime_get_window_mgr ();
970         iter = tny_list_create_iterator (headers);
971         not_opened_headers = tny_simple_list_new ();
972         
973         while (!tny_iterator_is_done (iter)) {
974
975                 ModestWindow *window = NULL;
976                 TnyHeader *header = NULL;
977                 gboolean found = FALSE;
978                 
979                 header = TNY_HEADER (tny_iterator_get_current (iter));
980                 if (header)
981                         flags = tny_header_get_flags (header);
982
983                 window = NULL;
984                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
985                 
986                 /* Do not open again the message and present the
987                    window to the user */
988                 if (found) {
989                         if (window)
990                                 gtk_window_present (GTK_WINDOW (window));
991                         else
992                                 /* the header has been registered already, we don't do
993                                  * anything but wait for the window to come up*/
994                                 g_debug ("header %p already registered, waiting for window", header);
995                 } else {
996                         tny_list_append (not_opened_headers, G_OBJECT (header));
997                 }
998
999                 if (header)
1000                         g_object_unref (header);
1001
1002                 tny_iterator_next (iter);
1003         }
1004         g_object_unref (iter);
1005         iter = NULL;
1006         
1007         /* If some messages would have to be downloaded, ask the user to 
1008          * make a connection. It's generally easier to do this here (in the mainloop) 
1009          * than later in a thread:
1010          */
1011         if (tny_list_get_length (not_opened_headers) > 0) {
1012                 TnyIterator *iter;
1013                 gboolean found = FALSE;
1014
1015                 iter = tny_list_create_iterator (not_opened_headers);
1016                 while (!tny_iterator_is_done (iter) && !found) {
1017                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1018                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1019                                 found = TRUE;
1020                         else
1021                                 tny_iterator_next (iter);
1022
1023                         g_object_unref (header);
1024                 }
1025                 g_object_unref (iter);
1026
1027                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1028                         g_object_unref (not_opened_headers);
1029                         return;                 
1030                 }
1031         }
1032         
1033         /* Register the headers before actually creating the windows: */
1034         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1035         while (!tny_iterator_is_done (iter_not_opened)) {
1036                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1037                 if (header) {
1038                         modest_window_mgr_register_header (mgr, header);
1039                         g_object_unref (header);
1040                 }
1041                 
1042                 tny_iterator_next (iter_not_opened);
1043         }
1044         g_object_unref (iter_not_opened);
1045         iter_not_opened = NULL;
1046         
1047         /* Open each message */
1048         if (tny_list_get_length (not_opened_headers) > 0) {
1049                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1050                                                                          G_OBJECT (win), 
1051                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1052                                                                          NULL);
1053                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1054                 if (tny_list_get_length (not_opened_headers) > 1) {
1055                         modest_mail_operation_get_msgs_full (mail_op, 
1056                                                              not_opened_headers, 
1057                                                              open_msg_cb, 
1058                                                              NULL, 
1059                                                              NULL);
1060                 } else {
1061                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1062                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1063                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1064                         g_object_unref (header);
1065                         g_object_unref (iter);
1066                 }
1067                 g_object_unref (mail_op);
1068         }
1069
1070         /* Clean */
1071         if (not_opened_headers != NULL)
1072                 g_object_unref (not_opened_headers);
1073 }
1074
1075 void
1076 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1077 {
1078         TnyList *headers;
1079
1080         /* Get headers */
1081         headers = get_selected_headers (win);
1082         if (!headers)
1083                 return;
1084
1085         /* Open them */
1086         _modest_ui_actions_open (headers, win);
1087
1088         g_object_unref(headers);
1089 }
1090
1091
1092 static void
1093 free_reply_forward_helper (gpointer data)
1094 {
1095         ReplyForwardHelper *helper;
1096
1097         helper = (ReplyForwardHelper *) data;
1098         g_free (helper->account_name);
1099         g_slice_free (ReplyForwardHelper, helper);
1100 }
1101
1102 static void
1103 reply_forward_cb (ModestMailOperation *mail_op, 
1104                   TnyHeader *header, 
1105                   TnyMsg *msg,
1106                   gpointer user_data)
1107 {
1108         TnyMsg *new_msg;
1109         ReplyForwardHelper *rf_helper;
1110         ModestWindow *msg_win = NULL;
1111         ModestEditType edit_type;
1112         gchar *from = NULL;
1113         TnyAccount *account = NULL;
1114         ModestWindowMgr *mgr = NULL;
1115         gchar *signature = NULL;
1116
1117         /* If there was any error. The mail operation could be NULL,
1118            this means that we already have the message downloaded and
1119            that we didn't do a mail operation to retrieve it */
1120         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1121                 return;
1122                         
1123         g_return_if_fail (user_data != NULL);
1124         rf_helper = (ReplyForwardHelper *) user_data;
1125
1126         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1127                                                    rf_helper->account_name);
1128         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1129                                          rf_helper->account_name,
1130                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1131                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1132                                                            rf_helper->account_name,
1133                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1134         }
1135
1136         /* Create reply mail */
1137         switch (rf_helper->action) {
1138         case ACTION_REPLY:
1139                 new_msg = 
1140                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1141                                                          rf_helper->reply_forward_type,
1142                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1143                 break;
1144         case ACTION_REPLY_TO_ALL:
1145                 new_msg = 
1146                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1147                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1148                 edit_type = MODEST_EDIT_TYPE_REPLY;
1149                 break;
1150         case ACTION_FORWARD:
1151                 new_msg = 
1152                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1153                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1154                 break;
1155         default:
1156                 g_return_if_reached ();
1157                 return;
1158         }
1159
1160         g_free (signature);
1161
1162         if (!new_msg) {
1163                 g_printerr ("modest: failed to create message\n");
1164                 goto cleanup;
1165         }
1166
1167         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1168                                                                        rf_helper->account_name,
1169                                                                        TNY_ACCOUNT_TYPE_STORE);
1170         if (!account) {
1171                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1172                 goto cleanup;
1173         }
1174
1175         /* Create and register the windows */
1176         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1177         mgr = modest_runtime_get_window_mgr ();
1178         modest_window_mgr_register_window (mgr, msg_win);
1179
1180         if (rf_helper->parent_window != NULL) {
1181                 gdouble parent_zoom;
1182
1183                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1184                 modest_window_set_zoom (msg_win, parent_zoom);
1185         }
1186
1187         /* Show edit window */
1188         gtk_widget_show_all (GTK_WIDGET (msg_win));
1189
1190 cleanup:
1191         if (msg_win)
1192                 g_object_unref (msg_win);
1193         if (new_msg)
1194                 g_object_unref (G_OBJECT (new_msg));
1195         if (account)
1196                 g_object_unref (G_OBJECT (account));
1197 /*      g_object_unref (msg); */
1198         free_reply_forward_helper (rf_helper);
1199 }
1200
1201 /*
1202  * Checks a list of headers. If any of them are not currently
1203  * downloaded (CACHED) then it asks the user for permission to
1204  * download them.
1205  *
1206  * Returns FALSE if the user does not want to download the
1207  * messages. Returns TRUE if the user allowed the download or if all
1208  * of them are currently downloaded
1209  */
1210 static gboolean
1211 download_uncached_messages (TnyList *header_list, 
1212                             GtkWindow *win)
1213 {
1214         TnyIterator *iter;
1215         gboolean retval;
1216         gint uncached_messages = 0;
1217
1218         iter = tny_list_create_iterator (header_list);
1219         while (!tny_iterator_is_done (iter)) {
1220                 TnyHeader *header;
1221
1222                 header = TNY_HEADER (tny_iterator_get_current (iter));
1223                 if (header) {
1224                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1225                                 uncached_messages ++;
1226                         g_object_unref (header);
1227                 }
1228
1229                 tny_iterator_next (iter);
1230         }
1231         g_object_unref (iter);
1232
1233         /* Ask for user permission to download the messages */
1234         retval = TRUE;
1235         if (uncached_messages > 0) {
1236                 gboolean download = TRUE;
1237                 if (!tny_device_is_online (modest_runtime_get_device())) {
1238                         GtkResponseType response =
1239                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1240                                                                          ngettext("mcen_nc_get_msg",
1241                                                                                   "mcen_nc_get_msgs",
1242                                                                                   uncached_messages));
1243                         if (response == GTK_RESPONSE_CANCEL) download = FALSE;
1244                 }
1245                 if (download) {
1246                         /* If a download will be necessary, make sure that we have a connection: */
1247                         retval = modest_platform_connect_and_wait(win, NULL);   
1248                 } else {
1249                         retval = FALSE;
1250                 }
1251         }
1252         return retval;
1253 }
1254
1255
1256 /*
1257  * Common code for the reply and forward actions
1258  */
1259 static void
1260 reply_forward (ReplyForwardAction action, ModestWindow *win)
1261 {
1262         ModestMailOperation *mail_op = NULL;
1263         TnyList *header_list = NULL;
1264         ReplyForwardHelper *rf_helper = NULL;
1265         guint reply_forward_type;
1266         gboolean continue_download = TRUE;
1267         gboolean do_retrieve = TRUE;
1268         
1269         g_return_if_fail (MODEST_IS_WINDOW(win));
1270
1271         /* we need an account when editing */
1272         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1273                 const gboolean created = modest_run_account_setup_wizard (win);
1274                 if (!created)
1275                         return;
1276         }
1277         
1278         header_list = get_selected_headers (win);
1279         if (!header_list)
1280                 return;
1281
1282         reply_forward_type = 
1283                 modest_conf_get_int (modest_runtime_get_conf (),
1284                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1285                                      NULL);
1286
1287         /* Check that the messages have been previously downloaded */
1288         do_retrieve = (action == ACTION_FORWARD) || (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1289         if (do_retrieve)
1290                 continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
1291         if (!continue_download) {
1292                 g_object_unref (header_list);
1293                 return;
1294         }
1295         
1296         /* We assume that we can only select messages of the
1297            same folder and that we reply all of them from the
1298            same account. In fact the interface currently only
1299            allows single selection */
1300         
1301         /* Fill helpers */
1302         rf_helper = g_slice_new0 (ReplyForwardHelper);
1303         rf_helper->reply_forward_type = reply_forward_type;
1304         rf_helper->action = action;
1305         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1306         
1307         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1308                 rf_helper->parent_window = GTK_WIDGET (win);
1309         if (!rf_helper->account_name)
1310                 rf_helper->account_name =
1311                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1312
1313         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1314                 TnyMsg *msg;
1315                 TnyHeader *header;
1316                 /* Get header and message. Do not free them here, the
1317                    reply_forward_cb must do it */
1318                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1319                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1320                 if (!msg || !header) {
1321                         if (msg)
1322                                 g_object_unref (msg);
1323                         g_printerr ("modest: no message found\n");
1324                         return;
1325                 } else {
1326                         reply_forward_cb (NULL, header, msg, rf_helper);
1327                 }
1328                 if (header)
1329                         g_object_unref (header);
1330         } else {
1331                 TnyHeader *header;
1332                 TnyIterator *iter;
1333
1334                 /* Only reply/forward to one message */
1335                 iter = tny_list_create_iterator (header_list);
1336                 header = TNY_HEADER (tny_iterator_get_current (iter));
1337                 g_object_unref (iter);
1338
1339                 if (header) {
1340                         /* Retrieve messages */
1341                         if (do_retrieve) {
1342                                 mail_op = modest_mail_operation_new_with_error_handling (
1343                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1344                                         G_OBJECT(win),
1345                                         modest_ui_actions_get_msgs_full_error_handler, 
1346                                         NULL);
1347                                 modest_mail_operation_queue_add (
1348                                         modest_runtime_get_mail_operation_queue (), mail_op);
1349                                 
1350                                 modest_mail_operation_get_msg (mail_op,
1351                                                                header,
1352                                                                reply_forward_cb,
1353                                                                rf_helper);
1354                                 /* Clean */
1355                                 g_object_unref(mail_op);
1356                         } else {
1357                                 /* we put a ref here to prevent double unref as the reply
1358                                  * forward callback unrefs the header at its end */
1359                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1360                         }
1361
1362
1363                         g_object_unref (header);
1364                 }
1365
1366         }
1367
1368         /* Free */
1369         g_object_unref (header_list);
1370 }
1371
1372 void
1373 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1374 {
1375         g_return_if_fail (MODEST_IS_WINDOW(win));
1376
1377         reply_forward (ACTION_REPLY, win);
1378 }
1379
1380 void
1381 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1382 {
1383         g_return_if_fail (MODEST_IS_WINDOW(win));
1384
1385         reply_forward (ACTION_FORWARD, win);
1386 }
1387
1388 void
1389 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1390 {
1391         g_return_if_fail (MODEST_IS_WINDOW(win));
1392
1393         reply_forward (ACTION_REPLY_TO_ALL, win);
1394 }
1395
1396 void 
1397 modest_ui_actions_on_next (GtkAction *action, 
1398                            ModestWindow *window)
1399 {
1400         if (MODEST_IS_MAIN_WINDOW (window)) {
1401                 GtkWidget *header_view;
1402
1403                 header_view = modest_main_window_get_child_widget (
1404                                 MODEST_MAIN_WINDOW(window),
1405                                 MODEST_WIDGET_TYPE_HEADER_VIEW);
1406                 if (!header_view)
1407                         return;
1408         
1409                 modest_header_view_select_next (
1410                                 MODEST_HEADER_VIEW(header_view)); 
1411         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1412                 modest_msg_view_window_select_next_message (
1413                                 MODEST_MSG_VIEW_WINDOW (window));
1414         } else {
1415                 g_return_if_reached ();
1416         }
1417 }
1418
1419 void 
1420 modest_ui_actions_on_prev (GtkAction *action, 
1421                            ModestWindow *window)
1422 {
1423         g_return_if_fail (MODEST_IS_WINDOW(window));
1424
1425         if (MODEST_IS_MAIN_WINDOW (window)) {
1426                 GtkWidget *header_view;
1427                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1428                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1429                 if (!header_view)
1430                         return;
1431                 
1432                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1433         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1434                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1435         } else {
1436                 g_return_if_reached ();
1437         }
1438 }
1439
1440 void 
1441 modest_ui_actions_on_sort (GtkAction *action, 
1442                            ModestWindow *window)
1443 {
1444         g_return_if_fail (MODEST_IS_WINDOW(window));
1445
1446         if (MODEST_IS_MAIN_WINDOW (window)) {
1447                 GtkWidget *header_view;
1448                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1449                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1450                 if (!header_view) {
1451                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1452
1453                         return;
1454                 }
1455
1456                 /* Show sorting dialog */
1457                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1458         }
1459 }
1460
1461 static void
1462 new_messages_arrived (ModestMailOperation *self, 
1463                       gint new_messages,
1464                       gpointer user_data)
1465 {
1466         ModestMainWindow *win = NULL;
1467         GtkWidget *folder_view = NULL;
1468         TnyFolderStore *folder = NULL;
1469         gboolean folder_empty = FALSE;
1470
1471         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1472         win = MODEST_MAIN_WINDOW (user_data);
1473
1474         /* Set contents style of headers view */
1475         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1476                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1477                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
1478                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1479                 
1480
1481                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1482                 
1483                 if (!folder_empty)
1484                         modest_main_window_set_contents_style (win,
1485                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1486         }       
1487
1488         /* Notify new messages have been downloaded */
1489         if (new_messages > 0)
1490                 modest_platform_on_new_msg ();
1491 }
1492
1493 /*
1494  * This function performs the send & receive required actions. The
1495  * window is used to create the mail operation. Typically it should
1496  * always be the main window, but we pass it as argument in order to
1497  * be more flexible.
1498  */
1499 void
1500 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1501 {
1502         gchar *acc_name = NULL;
1503         ModestMailOperation *mail_op;
1504
1505         /* If no account name was provided then get the current account, and if
1506            there is no current account then pick the default one: */
1507         if (!account_name) {
1508                 acc_name = g_strdup (modest_window_get_active_account(win));
1509                 if (!acc_name)
1510                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1511                 if (!acc_name) {
1512                         g_printerr ("modest: cannot get default account\n");
1513                         return;
1514                 }
1515         } else {
1516                 acc_name = g_strdup (account_name);
1517         }
1518
1519         /* Set send/receive operation in progress */    
1520         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1521
1522         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1523                                                                  G_OBJECT (win),
1524                                                                  modest_ui_actions_send_receive_error_handler,
1525                                                                  NULL);
1526
1527         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1528                           G_CALLBACK (_on_send_receive_progress_changed), 
1529                           win);
1530
1531         /* Send & receive. */
1532         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1533         /* Receive and then send. The operation is tagged initially as
1534            a receive operation because the account update performs a
1535            receive and then a send. The operation changes its type
1536            internally, so the progress objects will receive the proper
1537            progress information */
1538         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1539         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1540         g_object_unref (G_OBJECT (mail_op));
1541         
1542         /* Free */
1543         g_free (acc_name);
1544 }
1545
1546
1547 static void
1548 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1549                                   ModestWindow *win)
1550 {
1551         TnyTransportAccount *transport_account;
1552         TnySendQueue *send_queue = NULL;
1553         GError *error = NULL;
1554
1555         /* Get transport account */
1556         transport_account =
1557                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1558                                       (modest_runtime_get_account_store(),
1559                                        account_name,
1560                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1561         if (!transport_account) {
1562                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1563                 goto frees;
1564         }
1565
1566         /* Get send queue*/
1567         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1568         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1569                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1570                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1571                              "modest: could not find send queue for account\n");
1572         } else {
1573                 /* Keeep messages in outbox folder */
1574                 tny_send_queue_cancel (send_queue, FALSE, &error);
1575         }       
1576
1577  frees:
1578         if (transport_account != NULL) 
1579                 g_object_unref (G_OBJECT (transport_account));
1580 }
1581
1582 static void
1583 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1584 {
1585         GSList *account_names, *iter;
1586
1587         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1588                                                           TRUE);
1589
1590         iter = account_names;
1591         while (iter) {                  
1592                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1593                 iter = g_slist_next (iter);
1594         }
1595
1596         modest_account_mgr_free_account_names (account_names);
1597         account_names = NULL;
1598 }
1599
1600 void
1601 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1602
1603 {
1604         /* Check if accounts exist */
1605         gboolean accounts_exist = 
1606                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1607         
1608         /* If not, allow the user to create an account before trying to send/receive. */
1609         if (!accounts_exist)
1610                 modest_ui_actions_on_accounts (NULL, win);
1611         
1612         /* Cancel all sending operaitons */     
1613         modest_ui_actions_cancel_send_all (win);
1614 }
1615
1616 /*
1617  * Refreshes all accounts. This function will be used by automatic
1618  * updates
1619  */
1620 void
1621 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1622 {
1623         GSList *account_names, *iter;
1624
1625         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1626                                                           TRUE);
1627
1628         iter = account_names;
1629         while (iter) {                  
1630                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1631                 iter = g_slist_next (iter);
1632         }
1633
1634         modest_account_mgr_free_account_names (account_names);
1635         account_names = NULL;
1636 }
1637
1638 void 
1639 modest_do_refresh_current_folder(ModestWindow *win)
1640 {
1641         /* Refresh currently selected folder. Note that if we only
1642            want to retreive the headers, then the refresh only will
1643            invoke a poke_status over all folders, i.e., only the
1644            total/unread count will be updated */
1645         if (MODEST_IS_MAIN_WINDOW (win)) {
1646                 GtkWidget *header_view, *folder_view;
1647                 TnyFolderStore *folder_store;
1648
1649                 /* Get folder and header view */
1650                 folder_view = 
1651                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1652                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1653                 if (!folder_view)
1654                         return;
1655
1656                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1657
1658                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1659                         header_view = 
1660                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1661                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1662                 
1663                         /* We do not need to set the contents style
1664                            because it hasn't changed. We also do not
1665                            need to save the widget status. Just force
1666                            a refresh */
1667                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1668                                                        TNY_FOLDER (folder_store),
1669                                                        folder_refreshed_cb,
1670                                                        MODEST_MAIN_WINDOW (win));
1671                 }
1672                 
1673                 if (folder_store)
1674                         g_object_unref (folder_store);
1675         }
1676 }
1677
1678
1679 /*
1680  * Handler of the click on Send&Receive button in the main toolbar
1681  */
1682 void
1683 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1684 {
1685         /* Check if accounts exist */
1686         gboolean accounts_exist = 
1687                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1688         
1689         /* If not, allow the user to create an account before trying to send/receive. */
1690         if (!accounts_exist)
1691                 modest_ui_actions_on_accounts (NULL, win);
1692
1693         modest_do_refresh_current_folder (win);
1694         
1695         /* Refresh the active account */
1696         modest_ui_actions_do_send_receive (NULL, win);
1697 }
1698
1699
1700 void
1701 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1702 {
1703         ModestConf *conf;
1704         GtkWidget *header_view;
1705         
1706         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1707
1708         header_view = modest_main_window_get_child_widget (main_window,
1709                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1710         if (!header_view)
1711                 return;
1712
1713         conf = modest_runtime_get_conf ();
1714         
1715         /* what is saved/restored is depending on the style; thus; we save with
1716          * old style, then update the style, and restore for this new style
1717          */
1718         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1719         
1720         if (modest_header_view_get_style
1721             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1722                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1723                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1724         else
1725                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1726                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1727
1728         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1729                                       MODEST_CONF_HEADER_VIEW_KEY);
1730 }
1731
1732
1733 void 
1734 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1735                                       TnyHeader *header,
1736                                       ModestMainWindow *main_window)
1737 {
1738         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1739         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1740         
1741         /* in the case the folder is empty, show the empty folder message and focus
1742          * folder view */
1743         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1744                 if (modest_header_view_is_empty (header_view)) {
1745                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1746                         GtkWidget *folder_view = 
1747                                 modest_main_window_get_child_widget (main_window,
1748                                                                      MODEST_WIDGET_TYPE_FOLDER_VIEW);
1749                         if (folder != NULL) 
1750                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1751                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1752                         return;
1753                 }
1754         }
1755         /* If no header has been selected then exit */
1756         if (!header)
1757                 return;
1758
1759         /* Update focus */
1760         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1761             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1762
1763         /* Update toolbar dimming state */
1764         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1765 }
1766
1767 void
1768 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1769                                        TnyHeader *header,
1770                                        ModestMainWindow *main_window)
1771 {
1772         TnyList *headers;
1773
1774         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1775         
1776         if (!header)
1777                 return;
1778
1779
1780 /*      headers = tny_simple_list_new (); */
1781 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1782         headers = modest_header_view_get_selected_headers (header_view);
1783
1784         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1785
1786         g_object_unref (headers);
1787 }
1788
1789 static void
1790 set_active_account_from_tny_account (TnyAccount *account,
1791                                      ModestWindow *window)
1792 {
1793         const gchar *server_acc_name = tny_account_get_id (account);
1794         
1795         /* We need the TnyAccount provided by the
1796            account store because that is the one that
1797            knows the name of the Modest account */
1798         TnyAccount *modest_server_account = modest_server_account = 
1799                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1800                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1801                                                              server_acc_name);
1802         
1803         const gchar *modest_acc_name = 
1804                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1805         modest_window_set_active_account (window, modest_acc_name);
1806         g_object_unref (modest_server_account);
1807 }
1808
1809
1810 static void
1811 folder_refreshed_cb (ModestMailOperation *mail_op, 
1812                      TnyFolder *folder, 
1813                      gpointer user_data)
1814 {
1815         ModestMainWindow *win = NULL;
1816         GtkWidget *header_view;
1817         TnyFolder *current_folder;
1818         gboolean folder_empty = FALSE;
1819         gboolean all_marked_as_deleted = FALSE;
1820
1821         g_return_if_fail (TNY_IS_FOLDER (folder));
1822
1823         win = MODEST_MAIN_WINDOW (user_data);
1824         header_view = 
1825                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1826
1827         if (header_view) {
1828                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1829                 if (current_folder != NULL && folder != current_folder) {
1830                         return;
1831                 }
1832         }
1833
1834         /* Check if folder is empty and set headers view contents style */
1835         folder_empty = (tny_folder_get_all_count (folder) == 0);
1836         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1837         folder_empty = folder_empty || all_marked_as_deleted ;
1838         if (folder_empty) {
1839
1840                 printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1841                 modest_main_window_set_contents_style (win,
1842                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1843         } else {
1844                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1845         }
1846 }
1847
1848 void 
1849 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1850                                                TnyFolderStore *folder_store, 
1851                                                gboolean selected,
1852                                                ModestMainWindow *main_window)
1853 {
1854         ModestConf *conf;
1855         GtkWidget *header_view;
1856
1857         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1858
1859         header_view = modest_main_window_get_child_widget(main_window,
1860                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1861         if (!header_view)
1862                 return;
1863         
1864         conf = modest_runtime_get_conf ();
1865
1866         if (TNY_IS_ACCOUNT (folder_store)) {
1867                 if (selected) {
1868                         /* Update active account */
1869                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1870                         /* Show account details */
1871                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1872                 }
1873         } else {
1874                 if (TNY_IS_FOLDER (folder_store) && selected) {
1875                         
1876                         /* Update the active account */
1877                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1878                         if (account) {
1879                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1880                                 g_object_unref (account);
1881                                 account = NULL;
1882                         }
1883
1884                         /* Set the header style by default, it could
1885                            be changed later by the refresh callback to
1886                            empty */
1887                         modest_main_window_set_contents_style (main_window, 
1888                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1889
1890                         /* Set folder on header view. This function
1891                            will call tny_folder_refresh_async so we
1892                            pass a callback that will be called when
1893                            finished. We use that callback to set the
1894                            empty view if there are no messages */
1895                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1896                                                        TNY_FOLDER (folder_store),
1897                                                        folder_refreshed_cb,
1898                                                        main_window);
1899                         
1900                         /* Restore configuration. We need to do this
1901                            *after* the set_folder because the widget
1902                            memory asks the header view about its
1903                            folder  */
1904                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1905                                                       G_OBJECT(header_view),
1906                                                       MODEST_CONF_HEADER_VIEW_KEY);
1907                 } else {
1908                         /* Update the active account */
1909                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1910                         /* Save only if we're seeing headers */
1911                         if (modest_main_window_get_contents_style (main_window) ==
1912                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1913                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1914                                                            MODEST_CONF_HEADER_VIEW_KEY);
1915                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1916                 }
1917         }
1918
1919         /* Update toolbar dimming state */
1920         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1921 }
1922
1923 void 
1924 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1925                                      ModestWindow *win)
1926 {
1927         GtkWidget *dialog;
1928         gchar *txt, *item;
1929         gboolean online;
1930
1931         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1932         
1933         online = tny_device_is_online (modest_runtime_get_device());
1934
1935         if (online) {
1936                 /* already online -- the item is simply not there... */
1937                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1938                                                  GTK_DIALOG_MODAL,
1939                                                  GTK_MESSAGE_WARNING,
1940                                                  GTK_BUTTONS_NONE,
1941                                                  _("The %s you selected cannot be found"),
1942                                                  item);
1943                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
1944                 gtk_dialog_run (GTK_DIALOG(dialog));
1945         } else {
1946                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1947                                                       GTK_WINDOW (win),
1948                                                       GTK_DIALOG_MODAL,
1949                                                       _("mcen_bd_dialog_cancel"),
1950                                                       GTK_RESPONSE_REJECT,
1951                                                       _("mcen_bd_dialog_ok"),
1952                                                       GTK_RESPONSE_ACCEPT,
1953                                                       NULL);
1954                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1955                                          "Do you want to get online?"), item);
1956                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1957                                     gtk_label_new (txt), FALSE, FALSE, 0);
1958                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1959                 g_free (txt);
1960
1961                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1962                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1963                         /* TODO: Comment about why is this commented out: */
1964                         /* modest_platform_connect_and_wait (); */
1965                 }
1966         }
1967         gtk_widget_destroy (dialog);
1968 }
1969
1970 void
1971 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1972                                      ModestWindow *win)
1973 {
1974         /* g_message ("%s %s", __FUNCTION__, link); */
1975 }       
1976
1977
1978 void
1979 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1980                                         ModestWindow *win)
1981 {
1982         modest_platform_activate_uri (link);
1983 }
1984
1985 void
1986 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1987                                           ModestWindow *win)
1988 {
1989         modest_platform_show_uri_popup (link);
1990 }
1991
1992 void
1993 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1994                                              ModestWindow *win)
1995 {
1996         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1997 }
1998
1999 void
2000 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2001                                           const gchar *address,
2002                                           ModestWindow *win)
2003 {
2004         /* g_message ("%s %s", __FUNCTION__, address); */
2005 }
2006
2007 void
2008 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2009 {
2010         TnyTransportAccount *transport_account;
2011         ModestMailOperation *mail_operation;
2012         MsgData *data;
2013         gchar *account_name, *from;
2014         ModestAccountMgr *account_mgr;
2015         gchar *info_text = NULL;
2016
2017         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2018         
2019         data = modest_msg_edit_window_get_msg_data (edit_window);
2020
2021         account_mgr = modest_runtime_get_account_mgr();
2022         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2023         if (!account_name) 
2024                 account_name = modest_account_mgr_get_default_account (account_mgr);
2025         if (!account_name) {
2026                 g_printerr ("modest: no account found\n");
2027                 modest_msg_edit_window_free_msg_data (edit_window, data);
2028                 return;
2029         }
2030
2031         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2032                 account_name = g_strdup (data->account_name);
2033         }
2034
2035         transport_account =
2036                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2037                                       (modest_runtime_get_account_store(),
2038                                        account_name,
2039                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2040         if (!transport_account) {
2041                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2042                 g_free (account_name);
2043                 modest_msg_edit_window_free_msg_data (edit_window, data);
2044                 return;
2045         }
2046         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2047
2048         /* Create the mail operation */         
2049         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2050         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2051
2052         modest_mail_operation_save_to_drafts (mail_operation,
2053                                               transport_account,
2054                                               data->draft_msg,
2055                                               edit_window,
2056                                               from,
2057                                               data->to, 
2058                                               data->cc, 
2059                                               data->bcc,
2060                                               data->subject, 
2061                                               data->plain_body, 
2062                                               data->html_body,
2063                                               data->attachments,
2064                                               data->priority_flags);
2065         /* Frees */
2066         g_free (from);
2067         g_free (account_name);
2068         g_object_unref (G_OBJECT (transport_account));
2069         g_object_unref (G_OBJECT (mail_operation));
2070
2071         modest_msg_edit_window_free_msg_data (edit_window, data);
2072
2073         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2074         modest_platform_information_banner (NULL, NULL, info_text);
2075         g_free (info_text);
2076 }
2077
2078 /* For instance, when clicking the Send toolbar button when editing a message: */
2079 void
2080 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2081 {
2082         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2083
2084         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2085                 return;
2086         
2087         /* Offer the connection dialog, if necessary: */        
2088         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2089                 return;
2090         
2091         /* FIXME: Code added just for testing. The final version will
2092            use the send queue provided by tinymail and some
2093            classifier */
2094         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2095         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2096         if (!account_name) 
2097                 account_name = modest_account_mgr_get_default_account (account_mgr);
2098                 
2099         if (!account_name) {
2100                 /* Run account setup wizard */
2101                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2102                 if (!created)
2103                         return;
2104         }
2105         
2106         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2107
2108         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2109                 account_name = g_strdup (data->account_name);
2110         }
2111         
2112         /* Get the currently-active transport account for this modest account: */
2113         TnyTransportAccount *transport_account =
2114                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2115                                       (modest_runtime_get_account_store(),
2116                                        account_name));
2117         if (!transport_account) {
2118                 /* Run account setup wizard */
2119                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2120                 if (!created)
2121                         return;
2122         }
2123         
2124         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2125
2126         /* Create the mail operation */
2127         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2128         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2129
2130         modest_mail_operation_send_new_mail (mail_operation,
2131                                              transport_account,
2132                                              data->draft_msg,
2133                                              from,
2134                                              data->to, 
2135                                              data->cc, 
2136                                              data->bcc,
2137                                              data->subject, 
2138                                              data->plain_body, 
2139                                              data->html_body,
2140                                              data->attachments,
2141                                              data->priority_flags);
2142                                              
2143         /* Free data: */
2144         g_free (from);
2145         g_free (account_name);
2146         g_object_unref (G_OBJECT (transport_account));
2147         g_object_unref (G_OBJECT (mail_operation));
2148
2149         modest_msg_edit_window_free_msg_data (edit_window, data);
2150         modest_msg_edit_window_set_sent (edit_window, TRUE);
2151
2152         /* Save settings and close the window: */
2153         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2154 }
2155
2156 void 
2157 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2158                                   ModestMsgEditWindow *window)
2159 {
2160         ModestMsgEditFormatState *format_state = NULL;
2161
2162         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2163         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2164
2165         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2166                 return;
2167
2168         format_state = modest_msg_edit_window_get_format_state (window);
2169         g_return_if_fail (format_state != NULL);
2170
2171         format_state->bold = gtk_toggle_action_get_active (action);
2172         modest_msg_edit_window_set_format_state (window, format_state);
2173         g_free (format_state);
2174         
2175 }
2176
2177 void 
2178 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2179                                      ModestMsgEditWindow *window)
2180 {
2181         ModestMsgEditFormatState *format_state = NULL;
2182
2183         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2184         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2185
2186         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2187                 return;
2188
2189         format_state = modest_msg_edit_window_get_format_state (window);
2190         g_return_if_fail (format_state != NULL);
2191
2192         format_state->italics = gtk_toggle_action_get_active (action);
2193         modest_msg_edit_window_set_format_state (window, format_state);
2194         g_free (format_state);
2195         
2196 }
2197
2198 void 
2199 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2200                                      ModestMsgEditWindow *window)
2201 {
2202         ModestMsgEditFormatState *format_state = NULL;
2203
2204         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2205         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2206
2207         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2208                 return;
2209
2210         format_state = modest_msg_edit_window_get_format_state (window);
2211         g_return_if_fail (format_state != NULL);
2212
2213         format_state->bullet = gtk_toggle_action_get_active (action);
2214         modest_msg_edit_window_set_format_state (window, format_state);
2215         g_free (format_state);
2216         
2217 }
2218
2219 void 
2220 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2221                                      GtkRadioAction *selected,
2222                                      ModestMsgEditWindow *window)
2223 {
2224         ModestMsgEditFormatState *format_state = NULL;
2225         GtkJustification value;
2226
2227         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2228
2229         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2230                 return;
2231
2232         value = gtk_radio_action_get_current_value (selected);
2233
2234         format_state = modest_msg_edit_window_get_format_state (window);
2235         g_return_if_fail (format_state != NULL);
2236
2237         format_state->justification = value;
2238         modest_msg_edit_window_set_format_state (window, format_state);
2239         g_free (format_state);
2240 }
2241
2242 void 
2243 modest_ui_actions_on_select_editor_color (GtkAction *action,
2244                                           ModestMsgEditWindow *window)
2245 {
2246         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2247         g_return_if_fail (GTK_IS_ACTION (action));
2248
2249         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2250                 return;
2251
2252         modest_msg_edit_window_select_color (window);
2253 }
2254
2255 void 
2256 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2257                                                      ModestMsgEditWindow *window)
2258 {
2259         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2260         g_return_if_fail (GTK_IS_ACTION (action));
2261
2262         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2263                 return;
2264
2265         modest_msg_edit_window_select_background_color (window);
2266 }
2267
2268 void 
2269 modest_ui_actions_on_insert_image (GtkAction *action,
2270                                    ModestMsgEditWindow *window)
2271 {
2272         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2273         g_return_if_fail (GTK_IS_ACTION (action));
2274
2275         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2276                 return;
2277
2278         modest_msg_edit_window_insert_image (window);
2279 }
2280
2281 void 
2282 modest_ui_actions_on_attach_file (GtkAction *action,
2283                                   ModestMsgEditWindow *window)
2284 {
2285         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2286         g_return_if_fail (GTK_IS_ACTION (action));
2287
2288         modest_msg_edit_window_offer_attach_file (window);
2289 }
2290
2291 void 
2292 modest_ui_actions_on_remove_attachments (GtkAction *action,
2293                                          ModestMsgEditWindow *window)
2294 {
2295         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2296         g_return_if_fail (GTK_IS_ACTION (action));
2297
2298         modest_msg_edit_window_remove_attachments (window, NULL);
2299 }
2300
2301 static void
2302 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2303                                             gpointer user_data)
2304 {
2305         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2306         const GError *error = modest_mail_operation_get_error (mail_op);
2307
2308         if(error)
2309         {
2310                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2311                                                     modest_mail_operation_get_error (mail_op)->message);
2312         }
2313 }
2314
2315 static void
2316 modest_ui_actions_create_folder(GtkWidget *parent_window,
2317                                 GtkWidget *folder_view)
2318 {
2319         TnyFolderStore *parent_folder;
2320
2321         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2322         
2323         if (parent_folder) {
2324                 gboolean finished = FALSE;
2325                 gint result;
2326                 gchar *folder_name = NULL, *suggested_name = NULL;
2327                 const gchar *proto_str = NULL;
2328                 TnyAccount *account;
2329
2330                 if (TNY_IS_ACCOUNT (parent_folder))
2331                         account = g_object_ref (parent_folder);
2332                 else
2333                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2334                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2335
2336                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2337                     MODEST_PROTOCOL_STORE_POP) {
2338                         finished = TRUE;
2339                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2340                 }
2341                 g_object_unref (account);
2342
2343                 /* Run the new folder dialog */
2344                 while (!finished) {
2345                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2346                                                                         parent_folder,
2347                                                                         suggested_name,
2348                                                                         &folder_name);
2349
2350                         g_free (suggested_name);
2351                         suggested_name = NULL;
2352
2353                         if (result == GTK_RESPONSE_REJECT) {
2354                                 finished = TRUE;
2355                         } else {
2356                                 ModestMailOperation *mail_op;
2357                                 TnyFolder *new_folder = NULL;
2358
2359                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2360                                                                                           G_OBJECT(parent_window),
2361                                                                                           modest_ui_actions_new_folder_error_handler,
2362                                                                                           parent_window);
2363
2364                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2365                                                                  mail_op);
2366                                 new_folder = modest_mail_operation_create_folder (mail_op,
2367                                                                                   parent_folder,
2368                                                                                   (const gchar *) folder_name);
2369                                 if (new_folder) {
2370                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2371                                                                           new_folder, TRUE);
2372
2373                                         g_object_unref (new_folder);
2374                                         finished = TRUE;
2375                                 }
2376                                 g_object_unref (mail_op);
2377                         }
2378
2379                         suggested_name = folder_name;
2380                         folder_name = NULL;
2381                 }
2382
2383                 g_object_unref (parent_folder);
2384         }
2385 }
2386
2387 void 
2388 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2389 {
2390         GtkWidget *folder_view;
2391         
2392         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2393
2394         folder_view = modest_main_window_get_child_widget (main_window,
2395                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2396         if (!folder_view)
2397                 return;
2398
2399         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2400 }
2401
2402 static void
2403 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2404                                                gpointer user_data)
2405 {
2406         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2407         const GError *error = NULL;
2408         const gchar *message = NULL;
2409         
2410         /* Get error message */
2411         error = modest_mail_operation_get_error (mail_op);
2412         if (!error)
2413                 g_return_if_reached ();
2414
2415         switch (error->code) {
2416         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2417                 message = _CS("ckdg_ib_folder_already_exists");
2418                 break;
2419         default:
2420                 g_return_if_reached ();
2421         }
2422
2423         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2424 }
2425
2426 void 
2427 modest_ui_actions_on_rename_folder (GtkAction *action,
2428                                      ModestMainWindow *main_window)
2429 {
2430         TnyFolderStore *folder;
2431         GtkWidget *folder_view;
2432         GtkWidget *header_view; 
2433
2434         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2435
2436         folder_view = modest_main_window_get_child_widget (main_window,
2437                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2438         if (!folder_view)
2439                 return;
2440
2441         header_view = modest_main_window_get_child_widget (main_window,
2442                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2443         
2444         if (!header_view)
2445                 return;
2446
2447         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2448         if (!folder)
2449                 return;
2450
2451         /* Offer the connection dialog if necessary: */
2452         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2453                 g_object_unref (G_OBJECT (folder));
2454                 return;
2455         }
2456
2457         
2458         if (TNY_IS_FOLDER (folder)) {
2459                 gchar *folder_name;
2460                 gint response;
2461                 const gchar *current_name;
2462                 TnyFolderStore *parent;
2463
2464                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2465                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2466                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2467                                                                      parent, current_name, 
2468                                                                      &folder_name);
2469                 g_object_unref (parent);
2470
2471                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2472                         ModestMailOperation *mail_op;
2473                         GtkTreeSelection *sel = NULL;
2474
2475                         mail_op = 
2476                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2477                                                                                G_OBJECT(main_window),
2478                                                                                modest_ui_actions_rename_folder_error_handler,
2479                                                                                main_window);
2480                         
2481
2482                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2483                                                          mail_op);
2484
2485                         /* Clear the headers view */
2486                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2487                         gtk_tree_selection_unselect_all (sel);
2488
2489                         /* Select *after* the changes */
2490                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2491                                                           TNY_FOLDER(folder), TRUE);
2492
2493                         modest_mail_operation_rename_folder (mail_op,
2494                                                              TNY_FOLDER (folder),
2495                                                              (const gchar *) folder_name);
2496
2497                         g_object_unref (mail_op);
2498                         g_free (folder_name);
2499                 }
2500         }
2501         g_object_unref (folder);
2502 }
2503
2504 static void
2505 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2506                                                gpointer user_data)
2507 {
2508         GObject *win = modest_mail_operation_get_source (mail_op);
2509
2510         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2511                                                 _("mail_in_ui_folder_delete_error"));
2512         g_object_unref (win);
2513 }
2514
2515 static void
2516 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2517 {
2518         TnyFolderStore *folder;
2519         GtkWidget *folder_view;
2520         gint response;
2521         gchar *message;
2522         
2523         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2524
2525         folder_view = modest_main_window_get_child_widget (main_window,
2526                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2527         if (!folder_view)
2528                 return;
2529
2530         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2531
2532         /* Show an error if it's an account */
2533         if (!TNY_IS_FOLDER (folder)) {
2534                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2535                                                         _("mail_in_ui_folder_delete_error"));
2536                 g_object_unref (G_OBJECT (folder));
2537                 return ;
2538         }
2539
2540         /* Offer the connection dialog if necessary: */
2541         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2542                 g_object_unref (G_OBJECT (folder));
2543                 return;
2544         }
2545
2546         /* Ask the user */      
2547         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2548                                     tny_folder_get_name (TNY_FOLDER (folder)));
2549         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2550                                                             (const gchar *) message);
2551         g_free (message);
2552
2553         if (response == GTK_RESPONSE_OK) {
2554                 ModestMailOperation *mail_op;
2555                 GtkTreeSelection *sel;
2556
2557                 /* Unselect the folder before deleting it to free the headers */
2558                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2559                 gtk_tree_selection_unselect_all (sel);
2560
2561                 /* Create the mail operation */
2562                 mail_op =
2563                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2564                                                                        G_OBJECT(main_window),
2565                                                                        modest_ui_actions_delete_folder_error_handler,
2566                                                                        NULL);
2567
2568                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2569                                                  mail_op);
2570                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2571                 g_object_unref (G_OBJECT (mail_op));
2572         }
2573
2574         g_object_unref (G_OBJECT (folder));
2575 }
2576
2577 void 
2578 modest_ui_actions_on_delete_folder (GtkAction *action,
2579                                      ModestMainWindow *main_window)
2580 {
2581         GtkWidget *folder_view;
2582         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2583
2584         delete_folder (main_window, FALSE);
2585         folder_view = modest_main_window_get_child_widget (main_window,
2586                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2587         if (!folder_view)
2588                 return;
2589         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2590 }
2591
2592 void 
2593 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2594 {
2595         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2596         
2597         delete_folder (main_window, TRUE);
2598 }
2599
2600
2601 static void
2602 show_error (GtkWidget *parent_widget, const gchar* text)
2603 {
2604         hildon_banner_show_information(parent_widget, NULL, text);
2605         
2606 #if 0
2607         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2608         /*
2609           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2610           (GtkDialogFlags)0,
2611           GTK_MESSAGE_ERROR,
2612           GTK_BUTTONS_OK,
2613           text ));
2614         */
2615                  
2616         gtk_dialog_run (dialog);
2617         gtk_widget_destroy (GTK_WIDGET (dialog));
2618 #endif
2619 }
2620
2621 void
2622 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2623                                          const gchar* server_account_name,
2624                                          gchar **username,
2625                                          gchar **password, 
2626                                          gboolean *cancel, 
2627                                          gboolean *remember,
2628                                          ModestMainWindow *main_window)
2629 {
2630         g_return_if_fail(server_account_name);
2631         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2632         
2633         /* Initalize output parameters: */
2634         if (cancel)
2635                 *cancel = FALSE;
2636                 
2637         if (remember)
2638                 *remember = TRUE;
2639                 
2640 #ifdef MODEST_PLATFORM_MAEMO
2641         /* Maemo uses a different (awkward) button order,
2642          * It should probably just use gtk_alternative_dialog_button_order ().
2643          */
2644         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2645                                               NULL,
2646                                               GTK_DIALOG_MODAL,
2647                                               _("mcen_bd_dialog_ok"),
2648                                               GTK_RESPONSE_ACCEPT,
2649                                               _("mcen_bd_dialog_cancel"),
2650                                               GTK_RESPONSE_REJECT,
2651                                               NULL);
2652 #else
2653         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2654                                               NULL,
2655                                               GTK_DIALOG_MODAL,
2656                                               GTK_STOCK_CANCEL,
2657                                               GTK_RESPONSE_REJECT,
2658                                               GTK_STOCK_OK,
2659                                               GTK_RESPONSE_ACCEPT,
2660                                               NULL);
2661 #endif /* MODEST_PLATFORM_MAEMO */
2662
2663         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2664         
2665         gchar *server_name = modest_server_account_get_hostname (
2666                 modest_runtime_get_account_mgr(), server_account_name);
2667         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2668                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2669                 *cancel = TRUE;
2670                 return;
2671         }
2672         
2673         /* This causes a warning because the logical ID has no %s in it, 
2674          * though the translation does, but there is not much we can do about that: */
2675         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2676         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2677                             FALSE, FALSE, 0);
2678         g_free (txt);
2679         g_free (server_name);
2680         server_name = NULL;
2681
2682         /* username: */
2683         gchar *initial_username = modest_server_account_get_username (
2684                 modest_runtime_get_account_mgr(), server_account_name);
2685         
2686         GtkWidget *entry_username = gtk_entry_new ();
2687         if (initial_username)
2688                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2689         /* Dim this if a connection has ever succeeded with this username,
2690          * as per the UI spec: */
2691         const gboolean username_known = 
2692                 modest_server_account_get_username_has_succeeded(
2693                         modest_runtime_get_account_mgr(), server_account_name);
2694         gtk_widget_set_sensitive (entry_username, !username_known);
2695         
2696 #ifdef MODEST_PLATFORM_MAEMO
2697         /* Auto-capitalization is the default, so let's turn it off: */
2698         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2699         
2700         /* Create a size group to be used by all captions.
2701          * Note that HildonCaption does not create a default size group if we do not specify one.
2702          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2703         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2704         
2705         GtkWidget *caption = hildon_caption_new (sizegroup, 
2706                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2707         gtk_widget_show (entry_username);
2708         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2709                 FALSE, FALSE, MODEST_MARGIN_HALF);
2710         gtk_widget_show (caption);
2711 #else 
2712         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2713                             TRUE, FALSE, 0);
2714 #endif /* MODEST_PLATFORM_MAEMO */      
2715                             
2716         /* password: */
2717         GtkWidget *entry_password = gtk_entry_new ();
2718         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2719         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2720         
2721 #ifdef MODEST_PLATFORM_MAEMO
2722         /* Auto-capitalization is the default, so let's turn it off: */
2723         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2724                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2725         
2726         caption = hildon_caption_new (sizegroup, 
2727                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2728         gtk_widget_show (entry_password);
2729         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2730                 FALSE, FALSE, MODEST_MARGIN_HALF);
2731         gtk_widget_show (caption);
2732         g_object_unref (sizegroup);
2733 #else 
2734         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2735                             TRUE, FALSE, 0);
2736 #endif /* MODEST_PLATFORM_MAEMO */      
2737                                 
2738 /* This is not in the Maemo UI spec:
2739         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2740         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2741                             TRUE, FALSE, 0);
2742 */
2743
2744         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2745         
2746         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2747                 if (username) {
2748                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2749                         
2750                         modest_server_account_set_username (
2751                                  modest_runtime_get_account_mgr(), server_account_name, 
2752                                  *username);
2753                                  
2754                         const gboolean username_was_changed = 
2755                                 (strcmp (*username, initial_username) != 0);
2756                         if (username_was_changed) {
2757                                 g_warning ("%s: tinymail does not yet support changing the "
2758                                         "username in the get_password() callback.\n", __FUNCTION__);
2759                         }
2760                 }
2761                         
2762                 if (password) {
2763                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2764                         
2765                         /* We do not save the password in the configuration, 
2766                          * because this function is only called for passwords that should 
2767                          * not be remembered:
2768                         modest_server_account_set_password (
2769                                  modest_runtime_get_account_mgr(), server_account_name, 
2770                                  *password);
2771                         */
2772                 }
2773                 
2774                 if (cancel)
2775                         *cancel   = FALSE;
2776                         
2777         } else {
2778                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2779                 
2780                 if (username)
2781                         *username = NULL;
2782                         
2783                 if (password)
2784                         *password = NULL;
2785                         
2786                 if (cancel)
2787                         *cancel   = TRUE;
2788         }
2789
2790 /* This is not in the Maemo UI spec:
2791         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2792                 *remember = TRUE;
2793         else
2794                 *remember = FALSE;
2795 */
2796
2797         gtk_widget_destroy (dialog);
2798         
2799         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2800 }
2801
2802 void
2803 modest_ui_actions_on_cut (GtkAction *action,
2804                           ModestWindow *window)
2805 {
2806         GtkWidget *focused_widget;
2807         GtkClipboard *clipboard;
2808
2809         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2810         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2811         if (GTK_IS_EDITABLE (focused_widget)) {
2812                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2813                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2814                 gtk_clipboard_store (clipboard);
2815         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2816                 GtkTextBuffer *buffer;
2817
2818                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2819                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2820                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2821                 gtk_clipboard_store (clipboard);
2822         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2823                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2824         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2825                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2826         }
2827 }
2828
2829 void
2830 modest_ui_actions_on_copy (GtkAction *action,
2831                            ModestWindow *window)
2832 {
2833         GtkClipboard *clipboard;
2834         GtkWidget *focused_widget;
2835
2836         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2837         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2838
2839         if (GTK_IS_LABEL (focused_widget)) {
2840                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2841                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2842                 gtk_clipboard_store (clipboard);
2843         } else if (GTK_IS_EDITABLE (focused_widget)) {
2844                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2845                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2846                 gtk_clipboard_store (clipboard);
2847         } else if (GTK_IS_HTML (focused_widget)) {
2848                 gtk_html_copy (GTK_HTML (focused_widget));
2849                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2850                 gtk_clipboard_store (clipboard);
2851         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2852                 GtkTextBuffer *buffer;
2853                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2854                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2855                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2856                 gtk_clipboard_store (clipboard);
2857         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2858                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2859                 TnyIterator *iter = tny_list_create_iterator (header_list);
2860                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2861                 
2862                 gboolean ask = FALSE;
2863                 if (header) {
2864                         TnyFolder *folder = tny_header_get_folder (header);
2865                         TnyAccount *account = tny_folder_get_account (folder);
2866                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2867                         /* If it's POP then ask */
2868                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2869                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2870                         g_object_unref (account);
2871                         g_object_unref (folder);
2872                         g_object_unref (header);
2873                 }
2874
2875                 g_object_unref (iter);
2876                 
2877                 /* Check that the messages have been previously downloaded */
2878                 gboolean continue_download = TRUE;
2879                 if (ask)
2880                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2881                 if (continue_download)
2882                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2883                 g_object_unref (header_list);
2884         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2885                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2886         }    
2887
2888         /* Show information banner */
2889         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2890         
2891 }
2892
2893 void
2894 modest_ui_actions_on_undo (GtkAction *action,
2895                            ModestWindow *window)
2896 {
2897         ModestEmailClipboard *clipboard = NULL;
2898
2899         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2900                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2901         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2902                 /* Clear clipboard source */
2903                 clipboard = modest_runtime_get_email_clipboard ();
2904                 modest_email_clipboard_clear (clipboard);               
2905         }
2906         else {
2907                 g_return_if_reached ();
2908         }
2909 }
2910
2911 void
2912 modest_ui_actions_on_redo (GtkAction *action,
2913                            ModestWindow *window)
2914 {
2915         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2916                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2917         }
2918         else {
2919                 g_return_if_reached ();
2920         }
2921 }
2922
2923
2924 static void
2925 paste_msgs_cb (const GObject *object, gpointer user_data)
2926 {
2927         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2928         g_return_if_fail (GTK_IS_WIDGET (user_data));
2929         
2930         /* destroy information note */
2931         gtk_widget_destroy (GTK_WIDGET(user_data));
2932 }
2933
2934 static void
2935 paste_as_attachment_free (gpointer data)
2936 {
2937         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2938
2939         gtk_widget_destroy (helper->banner);
2940         g_object_unref (helper->banner);
2941         g_free (helper);
2942 }
2943
2944 static void
2945 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2946                             TnyHeader *header,
2947                             TnyMsg *msg,
2948                             gpointer userdata)
2949 {
2950         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2951         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2952
2953         if (msg == NULL)
2954                 return;
2955
2956         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2957         
2958 }
2959
2960 void
2961 modest_ui_actions_on_paste (GtkAction *action,
2962                             ModestWindow *window)
2963 {
2964         GtkWidget *focused_widget = NULL;
2965         GtkWidget *inf_note = NULL;
2966         ModestMailOperation *mail_op = NULL;
2967
2968         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2969         if (GTK_IS_EDITABLE (focused_widget)) {
2970                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2971         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2972                 ModestEmailClipboard *e_clipboard = NULL;
2973                 e_clipboard = modest_runtime_get_email_clipboard ();
2974                 if (modest_email_clipboard_cleared (e_clipboard)) {
2975                         GtkTextBuffer *buffer;
2976                         GtkClipboard *clipboard;
2977
2978                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2979                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2980                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2981                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2982                         ModestMailOperation *mail_op;
2983                         TnyFolder *src_folder;
2984                         TnyList *data;
2985                         gboolean delete;
2986                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2987                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2988                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2989                                                                            _CS("ckct_nw_pasting"));
2990                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2991                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2992                                                              G_OBJECT (window));
2993                         if (helper->banner != NULL) {
2994                                 g_object_ref (G_OBJECT (helper->banner));
2995                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2996                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2997                         }
2998
2999                         if (data != NULL) {
3000                                 modest_mail_operation_get_msgs_full (mail_op, 
3001                                                                      data,
3002                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3003                                                                      helper,
3004                                                                      paste_as_attachment_free);
3005                         }
3006                 }
3007         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3008                 ModestEmailClipboard *clipboard = NULL;
3009                 TnyFolder *src_folder = NULL;
3010                 TnyFolderStore *folder_store = NULL;
3011                 TnyList *data = NULL;           
3012                 gboolean delete = FALSE;
3013                 
3014                 /* Check clipboard source */
3015                 clipboard = modest_runtime_get_email_clipboard ();
3016                 if (modest_email_clipboard_cleared (clipboard)) 
3017                         return;
3018                 
3019                 /* Get elements to paste */
3020                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3021
3022                 /* Create a new mail operation */
3023                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3024                 
3025                 /* Get destination folder */
3026                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3027
3028                 /* transfer messages  */
3029                 if (data != NULL) {
3030                         gint response = 0;
3031
3032                         /* Ask for user confirmation */
3033                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3034                                                               TNY_FOLDER (folder_store), 
3035                                                               delete,
3036                                                               data);
3037                         
3038                         if (response == GTK_RESPONSE_OK) {
3039                                 /* Launch notification */
3040                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3041                                                                              _CS("ckct_nw_pasting"));
3042                                 if (inf_note != NULL)  {
3043                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3044                                         gtk_widget_show (GTK_WIDGET(inf_note));
3045                                 }
3046
3047                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3048                                 modest_mail_operation_xfer_msgs (mail_op, 
3049                                                                  data,
3050                                                                  TNY_FOLDER (folder_store),
3051                                                                  delete,
3052                                                                  paste_msgs_cb,
3053                                                                  inf_note);                             
3054                         } else {
3055                                 g_object_unref (mail_op);
3056                         }
3057                         
3058                 } else if (src_folder != NULL) {                        
3059                         /* Launch notification */
3060                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3061                                                                      _CS("ckct_nw_pasting"));
3062                         if (inf_note != NULL)  {
3063                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3064                                 gtk_widget_show (GTK_WIDGET(inf_note));
3065                         }
3066                         
3067                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3068                         modest_mail_operation_xfer_folder (mail_op, 
3069                                                            src_folder,
3070                                                            folder_store,
3071                                                            delete,
3072                                                            paste_msgs_cb,
3073                                                            inf_note);
3074                 }
3075
3076                 /* Free */
3077                 if (data != NULL) 
3078                         g_object_unref (data);
3079                 if (src_folder != NULL) 
3080                         g_object_unref (src_folder);
3081                 if (folder_store != NULL) 
3082                         g_object_unref (folder_store);
3083         }
3084 }
3085
3086
3087 void
3088 modest_ui_actions_on_select_all (GtkAction *action,
3089                                  ModestWindow *window)
3090 {
3091         GtkWidget *focused_widget;
3092
3093         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3094         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3095                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3096         } else if (GTK_IS_LABEL (focused_widget)) {
3097                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3098         } else if (GTK_IS_EDITABLE (focused_widget)) {
3099                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3100         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3101                 GtkTextBuffer *buffer;
3102                 GtkTextIter start, end;
3103
3104                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3105                 gtk_text_buffer_get_start_iter (buffer, &start);
3106                 gtk_text_buffer_get_end_iter (buffer, &end);
3107                 gtk_text_buffer_select_range (buffer, &start, &end);
3108         } else if (GTK_IS_HTML (focused_widget)) {
3109                 gtk_html_select_all (GTK_HTML (focused_widget));
3110         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3111                 GtkWidget *header_view = focused_widget;
3112                 GtkTreeSelection *selection = NULL;
3113                 
3114                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3115                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3116                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3117                 }
3118                                 
3119                 /* Disable window dimming management */
3120                 modest_window_disable_dimming (MODEST_WINDOW(window));
3121                 
3122                 /* Select all messages */
3123                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3124                 gtk_tree_selection_select_all (selection);
3125
3126                 /* Set focuse on header view */
3127                 gtk_widget_grab_focus (header_view);
3128
3129
3130                 /* Enable window dimming management */
3131                 modest_window_enable_dimming (MODEST_WINDOW(window));
3132                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3133         }
3134
3135 }
3136
3137 void
3138 modest_ui_actions_on_mark_as_read (GtkAction *action,
3139                                    ModestWindow *window)
3140 {       
3141         g_return_if_fail (MODEST_IS_WINDOW(window));
3142                 
3143         /* Mark each header as read */
3144         do_headers_action (window, headers_action_mark_as_read, NULL);
3145 }
3146
3147 void
3148 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3149                                      ModestWindow *window)
3150 {       
3151         g_return_if_fail (MODEST_IS_WINDOW(window));
3152                 
3153         /* Mark each header as read */
3154         do_headers_action (window, headers_action_mark_as_unread, NULL);
3155 }
3156
3157 void
3158 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3159                                   GtkRadioAction *selected,
3160                                   ModestWindow *window)
3161 {
3162         gint value;
3163
3164         value = gtk_radio_action_get_current_value (selected);
3165         if (MODEST_IS_WINDOW (window)) {
3166                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3167         }
3168 }
3169
3170 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3171                                                         GtkRadioAction *selected,
3172                                                         ModestWindow *window)
3173 {
3174         TnyHeaderFlags flags;
3175         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3176
3177         flags = gtk_radio_action_get_current_value (selected);
3178         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3179 }
3180
3181 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3182                                                            GtkRadioAction *selected,
3183                                                            ModestWindow *window)
3184 {
3185         gint file_format;
3186
3187         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3188
3189         file_format = gtk_radio_action_get_current_value (selected);
3190         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3191 }
3192
3193
3194 void     
3195 modest_ui_actions_on_zoom_plus (GtkAction *action,
3196                                 ModestWindow *window)
3197 {
3198         g_return_if_fail (MODEST_IS_WINDOW (window));
3199
3200         modest_window_zoom_plus (MODEST_WINDOW (window));
3201 }
3202
3203 void     
3204 modest_ui_actions_on_zoom_minus (GtkAction *action,
3205                                  ModestWindow *window)
3206 {
3207         g_return_if_fail (MODEST_IS_WINDOW (window));
3208
3209         modest_window_zoom_minus (MODEST_WINDOW (window));
3210 }
3211
3212 void     
3213 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3214                                            ModestWindow *window)
3215 {
3216         ModestWindowMgr *mgr;
3217         gboolean fullscreen, active;
3218         g_return_if_fail (MODEST_IS_WINDOW (window));
3219
3220         mgr = modest_runtime_get_window_mgr ();
3221
3222         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3223         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3224
3225         if (active != fullscreen) {
3226                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3227                 gtk_window_present (GTK_WINDOW (window));
3228         }
3229 }
3230
3231 void
3232 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3233                                         ModestWindow *window)
3234 {
3235         ModestWindowMgr *mgr;
3236         gboolean fullscreen;
3237
3238         g_return_if_fail (MODEST_IS_WINDOW (window));
3239
3240         mgr = modest_runtime_get_window_mgr ();
3241         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3242         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3243
3244         gtk_window_present (GTK_WINDOW (window));
3245 }
3246
3247 /* 
3248  * Used by modest_ui_actions_on_details to call do_headers_action 
3249  */
3250 static void
3251 headers_action_show_details (TnyHeader *header, 
3252                              ModestWindow *window,
3253                              gpointer user_data)
3254
3255 {
3256         GtkWidget *dialog;
3257         
3258         /* Create dialog */
3259         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3260
3261         /* Run dialog */
3262         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3263         gtk_widget_show_all (dialog);
3264         gtk_dialog_run (GTK_DIALOG (dialog));
3265
3266         gtk_widget_destroy (dialog);
3267 }
3268
3269 /*
3270  * Show the folder details in a ModestDetailsDialog widget
3271  */
3272 static void
3273 show_folder_details (TnyFolder *folder, 
3274                      GtkWindow *window)
3275 {
3276         GtkWidget *dialog;
3277         
3278         /* Create dialog */
3279         dialog = modest_details_dialog_new_with_folder (window, folder);
3280
3281         /* Run dialog */
3282         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3283         gtk_widget_show_all (dialog);
3284         gtk_dialog_run (GTK_DIALOG (dialog));
3285
3286         gtk_widget_destroy (dialog);
3287 }
3288
3289 /*
3290  * Show the header details in a ModestDetailsDialog widget
3291  */
3292 void     
3293 modest_ui_actions_on_details (GtkAction *action, 
3294                               ModestWindow *win)
3295 {
3296         TnyList * headers_list;
3297         TnyIterator *iter;
3298         TnyHeader *header;              
3299
3300         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3301                 TnyMsg *msg;
3302
3303                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3304                 if (!msg)
3305                         return;
3306                 g_object_unref (msg);           
3307
3308                 headers_list = get_selected_headers (win);
3309                 if (!headers_list)
3310                         return;
3311
3312                 iter = tny_list_create_iterator (headers_list);
3313
3314                 header = TNY_HEADER (tny_iterator_get_current (iter));
3315                 if (header) {
3316                         headers_action_show_details (header, win, NULL);
3317                         g_object_unref (header);
3318                 }
3319
3320                 g_object_unref (iter);
3321                 g_object_unref (headers_list);
3322
3323         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3324                 GtkWidget *folder_view, *header_view;
3325
3326                 /* Check which widget has the focus */
3327                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3328                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3329                 if (gtk_widget_is_focus (folder_view)) {
3330                         TnyFolderStore *folder_store
3331                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3332                         if (!folder_store) {
3333                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3334                                 return; 
3335                         }
3336                         /* Show only when it's a folder */
3337                         /* This function should not be called for account items, 
3338                          * because we dim the menu item for them. */
3339                         if (TNY_IS_FOLDER (folder_store)) {
3340                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3341                         }
3342
3343                         g_object_unref (folder_store);
3344
3345                 } else {
3346                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3347                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3348                         /* Show details of each header */
3349                         do_headers_action (win, headers_action_show_details, header_view);
3350                 }
3351         }
3352 }
3353
3354 void     
3355 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3356                                      ModestMsgEditWindow *window)
3357 {
3358         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3359
3360         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3361 }
3362
3363 void     
3364 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3365                                       ModestMsgEditWindow *window)
3366 {
3367         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3368
3369         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3370 }
3371
3372 void
3373 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3374                                        ModestMainWindow *main_window)
3375 {
3376         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3377
3378         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3379                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3380         else
3381                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3382 }
3383
3384 void 
3385 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3386                                      ModestWindow *window)
3387 {
3388         gboolean active, fullscreen = FALSE;
3389         ModestWindowMgr *mgr;
3390
3391         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3392
3393         /* Check if we want to toggle the toolbar vuew in fullscreen
3394            or normal mode */
3395         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3396                      "ViewShowToolbarFullScreen")) {
3397                 fullscreen = TRUE;
3398         }
3399
3400         /* Toggle toolbar */
3401         mgr = modest_runtime_get_window_mgr ();
3402         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3403 }
3404
3405 void     
3406 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3407                                            ModestMsgEditWindow *window)
3408 {
3409         modest_msg_edit_window_select_font (window);
3410 }
3411
3412 void
3413 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3414                                                   const gchar *display_name,
3415                                                   GtkWindow *window)
3416 {
3417         /* Do not change the application name if the widget has not
3418            the focus. This callback could be called even if the folder
3419            view has not the focus, because the handled signal could be
3420            emitted when the folder view is redrawn */
3421         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3422                 if (display_name)
3423                         gtk_window_set_title (window, display_name);
3424                 else
3425                         gtk_window_set_title (window, " ");
3426         }
3427 }
3428
3429 void
3430 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3431 {
3432         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3433         modest_msg_edit_window_select_contacts (window);
3434 }
3435
3436 void
3437 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3438 {
3439         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3440         modest_msg_edit_window_check_names (window, FALSE);
3441 }
3442
3443 static void
3444 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3445 {
3446         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3447                                          GTK_WIDGET (user_data));
3448 }
3449
3450 static GtkWidget*
3451 create_move_to_dialog (GtkWindow *win,
3452                        GtkWidget *folder_view,
3453                        GtkWidget **tree_view)
3454 {
3455         GtkWidget *dialog, *scroll;
3456         GtkWidget *new_button;
3457
3458         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3459                                               GTK_WINDOW (win),
3460                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3461                                               NULL);
3462
3463         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3464         /* We do this manually so GTK+ does not associate a response ID for
3465          * the button. */
3466         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3467         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3468         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3469
3470         /* Create scrolled window */
3471         scroll = gtk_scrolled_window_new (NULL, NULL);
3472         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3473                                          GTK_POLICY_AUTOMATIC,
3474                                          GTK_POLICY_AUTOMATIC);
3475
3476         /* Create folder view */
3477         *tree_view = modest_platform_create_folder_view (NULL);
3478
3479         g_signal_connect (G_OBJECT (new_button), 
3480                           "clicked", 
3481                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3482                           *tree_view);
3483
3484         /* It could happen that we're trying to move a message from a
3485            window (msg window for example) after the main window was
3486            closed, so we can not just get the model of the folder
3487            view */
3488         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3489                 const gchar *visible_id = NULL;
3490
3491                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3492                                                MODEST_FOLDER_VIEW(*tree_view));
3493
3494                 visible_id = 
3495                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3496
3497                 /* Show the same account than the one that is shown in the main window */
3498                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3499                                                                              visible_id);
3500         } else {
3501                 const gchar *active_account_name = NULL;
3502                 ModestAccountMgr *mgr = NULL;
3503                 ModestAccountData *acc_data = NULL;
3504
3505                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3506                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3507
3508                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3509                 mgr = modest_runtime_get_account_mgr ();
3510                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3511
3512                 /* Set the new visible & active account */
3513                 if (acc_data && acc_data->store_account) { 
3514                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3515                                                                                      acc_data->store_account->account_name);
3516                         modest_account_mgr_free_account_data (mgr, acc_data);
3517                 }
3518         }
3519
3520         /* Hide special folders */
3521         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3522         
3523         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3524
3525         /* Add scroll to dialog */
3526         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3527                             scroll, TRUE, TRUE, 0);
3528
3529         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3530         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3531
3532         return dialog;
3533 }
3534
3535 /*
3536  * Returns TRUE if at least one of the headers of the list belongs to
3537  * a message that has been fully retrieved.
3538  */
3539 #if 0 /* no longer in use. delete in 2007.10 */
3540 static gboolean
3541 has_retrieved_msgs (TnyList *list)
3542 {
3543         TnyIterator *iter;
3544         gboolean found = FALSE;
3545
3546         iter = tny_list_create_iterator (list);
3547         while (!tny_iterator_is_done (iter) && !found) {
3548                 TnyHeader *header;
3549                 TnyHeaderFlags flags = 0;
3550
3551                 header = TNY_HEADER (tny_iterator_get_current (iter));
3552                 if (header) {
3553                         flags = tny_header_get_flags (header);
3554                         if (flags & TNY_HEADER_FLAG_CACHED)
3555 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3556                                 found = TRUE;
3557
3558                         g_object_unref (header);
3559                 }
3560
3561                 if (!found)
3562                         tny_iterator_next (iter);
3563         }
3564         g_object_unref (iter);
3565
3566         return found;
3567 }
3568 #endif /* 0 */
3569
3570
3571 /*
3572  * Shows a confirmation dialog to the user when we're moving messages
3573  * from a remote server to the local storage. Returns the dialog
3574  * response. If it's other kind of movement the it always returns
3575  * GTK_RESPONSE_OK
3576  */
3577 gint
3578 msgs_move_to_confirmation (GtkWindow *win,
3579                            TnyFolder *dest_folder,
3580                            gboolean delete,
3581                            TnyList *headers)
3582 {
3583         gint response = GTK_RESPONSE_OK;
3584
3585         /* If the destination is a local folder (or MMC folder )*/
3586         if (!modest_tny_folder_is_remote_folder (dest_folder)) {
3587
3588                 gboolean is_online;
3589                 TnyDevice *device;
3590                 
3591                 TnyFolder *src_folder = NULL;
3592                 TnyIterator *iter = NULL;
3593                 TnyHeader *header = NULL;
3594
3595                 /* get the device */
3596                 
3597                 device = modest_runtime_get_device ();
3598                 if (device)
3599                         is_online = tny_device_is_online (device);
3600                 else {
3601                         g_warning ("failed to get tny device"); /* should not happend */
3602                         is_online = FALSE;
3603                 }
3604                                 
3605                 /* Get source folder */
3606                 iter = tny_list_create_iterator (headers);
3607                 header = TNY_HEADER (tny_iterator_get_current (iter));
3608                 if (header) {
3609                         src_folder = tny_header_get_folder (header);
3610                         g_object_unref (header);
3611                 }
3612
3613                 g_object_unref (iter);
3614
3615                 /* if no src_folder, message may be an attahcment */
3616                 if (src_folder == NULL) 
3617                         return GTK_RESPONSE_CANCEL;
3618
3619                 /* If the source is a remote folder */
3620                 if (!is_online && modest_tny_folder_is_remote_folder (src_folder)) {
3621
3622                         const gchar *message = NULL;
3623                         message = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs",
3624                                             tny_list_get_length (headers));
3625                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3626                                                                             (const gchar *) message);
3627                 } else
3628                         response = GTK_RESPONSE_OK;
3629                 
3630                 g_object_unref (src_folder);
3631         }
3632         
3633         return response;
3634 }
3635
3636
3637
3638 static void
3639 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3640 {
3641         ModestMsgViewWindow *self = NULL;
3642
3643         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3644         self = MODEST_MSG_VIEW_WINDOW (object);
3645         
3646         if (!modest_msg_view_window_select_next_message (self))
3647                 if (!modest_msg_view_window_select_previous_message (self))
3648                         /* No more messages to view, so close this window */
3649                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3650 }
3651
3652 void
3653 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3654                                              gpointer user_data)
3655 {
3656         GObject *win = modest_mail_operation_get_source (mail_op);
3657         const GError *error = NULL;
3658         const gchar *message = NULL;
3659         
3660         /* Get error message */
3661         error = modest_mail_operation_get_error (mail_op);
3662         if (error != NULL && error->message != NULL) {
3663                 message = error->message;
3664         } else {
3665                 message = _("mail_in_ui_folder_move_target_error");
3666         }
3667         
3668         /* Show notification dialog */
3669         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3670         g_object_unref (win);
3671 }
3672
3673 void
3674 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3675                                               gpointer user_data)
3676 {
3677         GObject *win = modest_mail_operation_get_source (mail_op);
3678         const GError *error = modest_mail_operation_get_error (mail_op);
3679
3680         g_return_if_fail (error != NULL);
3681         if (error->message != NULL)             
3682                 g_printerr ("modest: %s\n", error->message);
3683         else
3684                 g_printerr ("modest: unkonw error on send&receive operation");
3685
3686         /* Show error message */
3687 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3688 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3689 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3690 /*      else  */
3691 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3692 /*                                                      _CS("sfil_ib_unable_to_send")); */
3693         g_object_unref (win);
3694 }
3695
3696 static void
3697 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3698                        TnyHeader *header, 
3699                        TnyMsg *msg, 
3700                        gpointer user_data)
3701 {
3702         TnyList *parts;
3703         TnyIterator *iter;
3704         gint pending_purges = 0;
3705         gboolean some_purged = FALSE;
3706         ModestWindow *win = MODEST_WINDOW (user_data);
3707         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3708
3709         /* If there was any error */
3710         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3711                 modest_window_mgr_unregister_header (mgr, header);
3712                 return;
3713         }
3714
3715         /* Once the message has been retrieved for purging, we check if
3716          * it's all ok for purging */
3717
3718         parts = tny_simple_list_new ();
3719         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3720         iter = tny_list_create_iterator (parts);
3721
3722         while (!tny_iterator_is_done (iter)) {
3723                 TnyMimePart *part;
3724                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3725                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3726                         if (tny_mime_part_is_purged (part))
3727                                 some_purged = TRUE;
3728                         else
3729                                 pending_purges++;
3730                 }
3731
3732                 if (part)
3733                         g_object_unref (part);
3734
3735                 tny_iterator_next (iter);
3736         }
3737
3738         if (pending_purges>0) {
3739                 gint response;
3740                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3741
3742                 if (response == GTK_RESPONSE_OK) {
3743                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3744                         tny_iterator_first (iter);
3745                         while (!tny_iterator_is_done (iter)) {
3746                                 TnyMimePart *part;
3747                                 
3748                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3749                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3750                                         tny_mime_part_set_purged (part);
3751
3752                                 if (part)
3753                                         g_object_unref (part);
3754
3755                                 tny_iterator_next (iter);
3756                         }
3757                         
3758                         tny_msg_rewrite_cache (msg);
3759                 }
3760         } else {
3761                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3762         }
3763
3764         /* remove attachments */
3765         tny_iterator_first (iter);
3766         while (!tny_iterator_is_done (iter)) {
3767                 TnyMimePart *part;
3768                         
3769                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3770                 if (part) {
3771                         /* One for the reference given by tny_iterator_get_current(): */
3772                         g_object_unref (part);
3773
3774                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
3775                          * Otherwise, this seems useless. */
3776                 }
3777
3778                 tny_iterator_next (iter);
3779         }
3780         modest_window_mgr_unregister_header (mgr, header);
3781
3782         g_object_unref (iter);
3783         g_object_unref (parts);
3784 }
3785
3786 static void
3787 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3788                                                      ModestMainWindow *win)
3789 {
3790         GtkWidget *header_view;
3791         TnyList *header_list;
3792         TnyIterator *iter;
3793         TnyHeader *header;
3794         TnyHeaderFlags flags;
3795         ModestWindow *msg_view_window =  NULL;
3796         gboolean found;
3797
3798         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3799
3800         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3801                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3802
3803         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3804
3805         if (tny_list_get_length (header_list) == 1) {
3806                 iter = tny_list_create_iterator (header_list);
3807                 header = TNY_HEADER (tny_iterator_get_current (iter));
3808                 g_object_unref (iter);
3809         } else {
3810                 return;
3811         }
3812
3813         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3814                                                           header, &msg_view_window);
3815         flags = tny_header_get_flags (header);
3816         if (!(flags & TNY_HEADER_FLAG_CACHED))
3817                 return;
3818         if (found) {
3819                 if (msg_view_window != NULL) 
3820                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3821                 else {
3822                         /* do nothing; uid was registered before, so window is probably on it's way */
3823                         g_warning ("debug: header %p has already been registered", header);
3824                 }
3825         } else {
3826                 ModestMailOperation *mail_op = NULL;
3827                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3828                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3829                                                                          G_OBJECT (win),
3830                                                                          modest_ui_actions_get_msgs_full_error_handler,
3831                                                                          NULL);
3832                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3833                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3834                 
3835                 g_object_unref (mail_op);
3836         }
3837         if (header)
3838                 g_object_unref (header);
3839         if (header_list)
3840                 g_object_unref (header_list);
3841 }
3842
3843 /**
3844  * Utility function that transfer messages from both the main window
3845  * and the msg view window when using the "Move to" dialog
3846  */
3847 static void
3848 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3849                                               ModestWindow *win)
3850 {
3851         TnyList *headers = NULL;
3852         gint response = 0;
3853         TnyAccount *dst_account = NULL;
3854         const gchar *proto_str = NULL;
3855         gboolean dst_is_pop = FALSE;
3856
3857         if (!TNY_IS_FOLDER (dst_folder)) {
3858                 modest_platform_information_banner (GTK_WIDGET (win),
3859                                                     NULL,
3860                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3861                 return;
3862         }
3863
3864         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
3865         proto_str = tny_account_get_proto (dst_account);
3866
3867         /* tinymail will return NULL for local folders it seems */
3868         dst_is_pop = proto_str &&
3869                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
3870                  MODEST_PROTOCOL_STORE_POP);
3871
3872         g_object_unref (dst_account);
3873
3874         /* Get selected headers */
3875         headers = get_selected_headers (MODEST_WINDOW (win));
3876
3877         if (dst_is_pop) {
3878                 modest_platform_information_banner (GTK_WIDGET (win),
3879                                                     NULL,
3880                                                     ngettext("mail_in_ui_folder_move_target_error",
3881                                                              "mail_in_ui_folder_move_targets_error",
3882                                                              tny_list_get_length (headers)));
3883                 g_object_unref (headers);
3884                 return;
3885         }
3886
3887         /* Ask for user confirmation */
3888         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3889                                               TNY_FOLDER (dst_folder), 
3890                                               TRUE,
3891                                               headers);
3892
3893         /* Transfer messages */
3894         if (response == GTK_RESPONSE_OK) {
3895                 ModestMailOperation *mail_op = 
3896                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3897                                                                        G_OBJECT(win),
3898                                                                        modest_ui_actions_move_folder_error_handler,
3899                                                                        NULL);
3900                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3901                                                  mail_op);
3902
3903                 modest_mail_operation_xfer_msgs (mail_op, 
3904                                                  headers,
3905                                                  TNY_FOLDER (dst_folder),
3906                                                  TRUE,
3907                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3908                                                  NULL);
3909
3910                 g_object_unref (G_OBJECT (mail_op));
3911         }
3912         g_object_unref (headers);
3913 }
3914
3915 /*
3916  * UI handler for the "Move to" action when invoked from the
3917  * ModestMainWindow
3918  */
3919 static void 
3920 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3921                                           GtkWidget *folder_view,
3922                                           TnyFolderStore *dst_folder,
3923                                           ModestMainWindow *win)
3924 {
3925         GtkWidget *header_view = NULL;
3926         ModestMailOperation *mail_op = NULL;
3927         TnyFolderStore *src_folder;
3928
3929         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3930
3931         /* Get the source folder */
3932         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3933         
3934         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3935         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3936                                                                       src_folder))
3937                 goto end;
3938
3939         /* Get header view */
3940         header_view = 
3941                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3942
3943         /* Get folder or messages to transfer */
3944         if (gtk_widget_is_focus (folder_view)) {
3945                 GtkTreeSelection *sel;
3946
3947                 /* Allow only to transfer folders to the local root folder */
3948                 if (TNY_IS_ACCOUNT (dst_folder) && 
3949                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3950                         goto end;
3951                 
3952                 /* Clean folder on header view before moving it */
3953                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3954                 gtk_tree_selection_unselect_all (sel);
3955
3956                 if (TNY_IS_FOLDER (src_folder)) {
3957                         mail_op = 
3958                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3959                                                                                G_OBJECT(win),
3960                                                                                modest_ui_actions_move_folder_error_handler,
3961                                                                                NULL);
3962                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3963                                                          mail_op);
3964
3965                         modest_mail_operation_xfer_folder (mail_op, 
3966                                                            TNY_FOLDER (src_folder),
3967                                                            dst_folder,
3968                                                            TRUE, NULL, NULL);
3969                         /* Unref mail operation */
3970                         g_object_unref (G_OBJECT (mail_op));
3971                 } else {
3972                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3973                 }
3974         } else if (gtk_widget_is_focus (header_view)) {
3975                 /* Transfer messages */
3976                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3977         }
3978         
3979  end:
3980     if (src_folder)
3981         g_object_unref (src_folder);
3982 }
3983
3984
3985 /*
3986  * UI handler for the "Move to" action when invoked from the
3987  * ModestMsgViewWindow
3988  */
3989 static void 
3990 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3991                                               TnyFolderStore *dst_folder,
3992                                               ModestMsgViewWindow *win)
3993 {
3994         TnyHeader *header = NULL;
3995         TnyFolder *src_folder;
3996
3997         /* Create header list */
3998         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3999         src_folder = tny_header_get_folder(header);
4000         g_object_unref (header);
4001
4002         /* Transfer the message */
4003         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
4004                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4005
4006         g_object_unref (src_folder);
4007 }
4008
4009 void 
4010 modest_ui_actions_on_move_to (GtkAction *action, 
4011                               ModestWindow *win)
4012 {
4013         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4014         gint result = 0;
4015         TnyFolderStore *dst_folder = NULL;
4016         ModestMainWindow *main_window;
4017
4018         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4019                           MODEST_IS_MSG_VIEW_WINDOW (win));
4020
4021         /* Get the main window if exists */
4022         if (MODEST_IS_MAIN_WINDOW (win))
4023                 main_window = MODEST_MAIN_WINDOW (win);
4024         else
4025                 main_window = 
4026                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4027
4028         /* Get the folder view widget if exists */
4029         if (main_window)
4030                 folder_view = modest_main_window_get_child_widget (main_window,
4031                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
4032         else
4033                 folder_view = NULL;
4034
4035         /* Create and run the dialog */
4036         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4037         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4038         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4039         result = gtk_dialog_run (GTK_DIALOG(dialog));
4040         g_object_ref (tree_view);
4041         gtk_widget_destroy (dialog);
4042
4043         if (result != GTK_RESPONSE_ACCEPT)
4044                 return;
4045
4046         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4047         /* Offer the connection dialog if necessary: */
4048         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
4049                                                                       dst_folder)) {
4050
4051                 /* Do window specific stuff */
4052                 if (MODEST_IS_MAIN_WINDOW (win))
4053                         modest_ui_actions_on_main_window_move_to (action,
4054                                                                   folder_view,
4055                                                                   dst_folder,
4056                                                                   MODEST_MAIN_WINDOW (win));
4057                 else
4058                         modest_ui_actions_on_msg_view_window_move_to (action,
4059                                                                       dst_folder,
4060                                                                       MODEST_MSG_VIEW_WINDOW (win));
4061         }
4062         if (dst_folder)
4063                 g_object_unref (dst_folder);
4064 }
4065
4066 /*
4067  * Calls #HeadersFunc for each header already selected in the main
4068  * window or the message currently being shown in the msg view window
4069  */
4070 static void
4071 do_headers_action (ModestWindow *win, 
4072                    HeadersFunc func,
4073                    gpointer user_data)
4074 {
4075         TnyList *headers_list = NULL;
4076         TnyIterator *iter = NULL;
4077         TnyHeader *header = NULL;
4078         TnyFolder *folder = NULL;
4079
4080         /* Get headers */
4081         headers_list = get_selected_headers (win);
4082         if (!headers_list)
4083                 return;
4084
4085         /* Get the folder */
4086         iter = tny_list_create_iterator (headers_list);
4087         header = TNY_HEADER (tny_iterator_get_current (iter));
4088         if (header) {
4089                 folder = tny_header_get_folder (header);
4090                 g_object_unref (header);
4091         }
4092
4093         /* Call the function for each header */
4094         while (!tny_iterator_is_done (iter)) {
4095                 header = TNY_HEADER (tny_iterator_get_current (iter));
4096                 func (header, win, user_data);
4097                 g_object_unref (header);
4098                 tny_iterator_next (iter);
4099         }
4100
4101         /* Trick: do a poke status in order to speed up the signaling
4102            of observers */
4103         tny_folder_poke_status (folder);
4104
4105         /* Frees */
4106         g_object_unref (folder);
4107         g_object_unref (iter);
4108         g_object_unref (headers_list);
4109 }
4110
4111 void 
4112 modest_ui_actions_view_attachment (GtkAction *action,
4113                                    ModestWindow *window)
4114 {
4115         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4116                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4117         } else {
4118                 /* not supported window for this action */
4119                 g_return_if_reached ();
4120         }
4121 }
4122
4123 void
4124 modest_ui_actions_save_attachments (GtkAction *action,
4125                                     ModestWindow *window)
4126 {
4127         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4128                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4129         } else {
4130                 /* not supported window for this action */
4131                 g_return_if_reached ();
4132         }
4133 }
4134
4135 void
4136 modest_ui_actions_remove_attachments (GtkAction *action,
4137                                       ModestWindow *window)
4138 {
4139         if (MODEST_IS_MAIN_WINDOW (window)) {
4140                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4141         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4142                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4143         } else {
4144                 /* not supported window for this action */
4145                 g_return_if_reached ();
4146         }
4147 }
4148
4149 void 
4150 modest_ui_actions_on_settings (GtkAction *action, 
4151                                ModestWindow *win)
4152 {
4153         GtkWidget *dialog;
4154
4155         dialog = modest_platform_get_global_settings_dialog ();
4156         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4157         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4158         gtk_widget_show_all (dialog);
4159
4160         gtk_dialog_run (GTK_DIALOG (dialog));
4161
4162         gtk_widget_destroy (dialog);
4163 }
4164
4165 void 
4166 modest_ui_actions_on_help (GtkAction *action, 
4167                            ModestWindow *win)
4168 {
4169         const gchar *help_id = NULL;
4170
4171         if (MODEST_IS_MAIN_WINDOW (win)) {
4172                 const gchar *action_name;
4173                 action_name = gtk_action_get_name (action);
4174
4175                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
4176                     !strcmp (action_name, "HeaderViewCSMHelp")) {
4177                         GtkWidget *folder_view;
4178                         TnyFolderStore *folder_store;
4179                         /* Get selected folder */
4180                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4181                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
4182                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4183
4184                         /* Switch help_id */
4185                         if (TNY_IS_FOLDER (folder_store)) {
4186                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4187                                 case TNY_FOLDER_TYPE_NORMAL:
4188                                         help_id = "applications_email_managefolders";
4189                                         break;
4190                                 case TNY_FOLDER_TYPE_INBOX:
4191                                         help_id = "applications_email_inbox";
4192                                         break;
4193                                 case TNY_FOLDER_TYPE_OUTBOX:
4194                                         help_id = "applications_email_outbox";
4195                                         break;
4196                                 case TNY_FOLDER_TYPE_SENT:
4197                                         help_id = "applications_email_sent";
4198                                         break;
4199                                 case TNY_FOLDER_TYPE_DRAFTS:
4200                                         help_id = "applications_email_drafts";
4201                                         break;
4202                                 case TNY_FOLDER_TYPE_ARCHIVE:
4203                                         help_id = "applications_email_managefolders";
4204                                         break;
4205                                 default:
4206                                         help_id = "applications_email_managefolders";
4207                                 }
4208                         } else {
4209                                 help_id = "applications_email_mainview";        
4210                         }
4211                         g_object_unref (folder_store);
4212                 } else {
4213                         help_id = "applications_email_mainview";        
4214                 }
4215         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4216                 help_id = "applications_email_viewer";
4217         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4218                 help_id = "applications_email_editor";
4219
4220         modest_platform_show_help (GTK_WINDOW (win), help_id);
4221 }
4222
4223 void 
4224 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4225                                             ModestWindow *window)
4226 {
4227         ModestMailOperation *mail_op;
4228         TnyList *headers;
4229
4230         /* Get headers */
4231         headers = get_selected_headers (window);
4232         if (!headers)
4233                 return;
4234
4235         /* Create mail operation */
4236         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4237                                                                  G_OBJECT (window),
4238                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4239                                                                  NULL);
4240         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4241         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4242
4243         /* Frees */
4244         g_object_unref (headers);
4245         g_object_unref (mail_op);
4246 }
4247
4248 void
4249 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4250                                           ModestWindow *window)
4251 {
4252         g_return_if_fail (MODEST_IS_WINDOW (window));
4253         
4254         /* Update dimmed */     
4255         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4256 }
4257
4258 void
4259 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4260                                           ModestWindow *window)
4261 {
4262         g_return_if_fail (MODEST_IS_WINDOW (window));
4263
4264         /* Update dimmed */     
4265         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4266 }
4267
4268 void
4269 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4270                                           ModestWindow *window)
4271 {
4272         g_return_if_fail (MODEST_IS_WINDOW (window));
4273
4274         /* Update dimmed */     
4275         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4276 }
4277
4278 void
4279 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4280                                           ModestWindow *window)
4281 {
4282         g_return_if_fail (MODEST_IS_WINDOW (window));
4283
4284         /* Update dimmed */     
4285         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4286 }
4287
4288 void
4289 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4290                                           ModestWindow *window)
4291 {
4292         g_return_if_fail (MODEST_IS_WINDOW (window));
4293
4294         /* Update dimmed */     
4295         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4296 }
4297
4298 void
4299 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4300                                                  ModestWindow *window)
4301 {
4302         g_return_if_fail (MODEST_IS_WINDOW (window));
4303
4304         /* Update dimmed */     
4305         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4306 }
4307
4308 void
4309 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4310                                                      ModestWindow *window)
4311 {
4312         g_return_if_fail (MODEST_IS_WINDOW (window));
4313
4314         /* Update dimmed */     
4315         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4316 }
4317
4318 void
4319 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4320                                                      ModestWindow *window)
4321 {
4322         g_return_if_fail (MODEST_IS_WINDOW (window));
4323
4324         /* Update dimmed */     
4325         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4326 }
4327
4328 void
4329 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4330 {
4331         g_return_if_fail (MODEST_IS_WINDOW (window));
4332
4333         /* Update dimmed */     
4334         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4335 }
4336
4337 void
4338 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4339 {
4340         g_return_if_fail (MODEST_IS_WINDOW (window));
4341
4342         modest_platform_show_search_messages (GTK_WINDOW (window));
4343 }
4344
4345 void     
4346 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4347 {
4348         g_return_if_fail (MODEST_IS_WINDOW (win));
4349         modest_platform_show_addressbook (GTK_WINDOW (win));
4350 }
4351
4352
4353 void
4354 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4355                                           ModestWindow *window)
4356 {
4357         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4358
4359         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4360 }
4361
4362 static void 
4363 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4364                                    ModestMailOperationState *state,
4365                                    gpointer user_data)
4366 {
4367         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4368
4369         /* Set send/receive operation finished */       
4370         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4371                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4372         
4373 }
4374
4375