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