* Renamed a function
[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         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
407                                                             message);
408         
409
410         if (response == GTK_RESPONSE_OK) {      
411                 ModestWindow *main_window = NULL;
412                 ModestWindowMgr *mgr = NULL;
413                 GtkTreeModel *model = NULL;
414                 GtkTreeSelection *sel = NULL;
415                 GList *sel_list = NULL, *tmp = NULL;
416                 GtkTreeRowReference *row_reference = NULL;
417                 GtkTreePath *next_path = NULL;
418                 TnyFolder *folder = NULL;
419                 GError *err = NULL;
420
421                 /* Find last selected row */                    
422                 if (MODEST_IS_MAIN_WINDOW (win)) {
423                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
424                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
425                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
426                         for (tmp=sel_list; tmp; tmp=tmp->next) {
427                                 if (tmp->next == NULL) {
428                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
429                                         gtk_tree_path_next (next_path);
430                                         row_reference = gtk_tree_row_reference_new (model, next_path);
431                                         gtk_tree_path_free (next_path);
432                                 }
433                         }
434                 }
435                 
436                 /* Remove each header. If it's a view window header_view == NULL */
437                 do_headers_action (win, headers_action_delete, header_view);
438
439                 /* refresh the header view (removing marked-as-deleted)*/
440                 modest_header_view_refilter (MODEST_HEADER_VIEW(header_view)); 
441                 
442                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
443                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
444                         
445                         /* Get main window */
446                         mgr = modest_runtime_get_window_mgr ();
447                         main_window = modest_window_mgr_get_main_window (mgr);
448                 }
449                 else {                  
450                         /* Move cursor to next row */
451                         main_window = win; 
452
453                         /* Select next row */
454                         if (gtk_tree_row_reference_valid (row_reference)) {
455                                 next_path = gtk_tree_row_reference_get_path (row_reference);
456                                 gtk_tree_selection_select_path (sel, next_path);
457                                 gtk_tree_path_free (next_path);
458                         }
459                         if (row_reference != NULL)
460                                 gtk_tree_row_reference_free (row_reference);
461                 }
462
463                 /* Get folder from first header and sync it */
464                 iter = tny_list_create_iterator (header_list);
465                 header = TNY_HEADER (tny_iterator_get_current (iter));
466                 folder = tny_header_get_folder (header);
467                 if (TNY_IS_CAMEL_IMAP_FOLDER (folder))
468 /*                      tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* FALSE --> don't expunge *\/ */
469                         tny_folder_sync (folder, FALSE, &err); /* FALSE --> don't expunge */
470                 else if (TNY_IS_CAMEL_POP_FOLDER (folder))
471 /*                      tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* TRUE --> dont expunge *\/ */
472                         tny_folder_sync (folder, TRUE, &err); /* TRUE --> expunge */
473                 else
474                         /* local folders */
475 /*                      tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /\* TRUE --> expunge *\/ */
476                         tny_folder_sync (folder, TRUE, &err); /* TRUE --> expunge */
477
478                 if (err != NULL) {
479                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
480                         g_error_free(err);
481                 }
482
483                 g_object_unref (header);
484                 g_object_unref (iter);
485                 g_object_unref (folder);
486                 
487                 /* Update toolbar dimming state */
488                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
489
490                 /* Free */
491                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
492                 g_list_free (sel_list);
493         }
494
495         /* Free*/
496         g_free(message);
497         g_free(desc);
498         g_object_unref (header_list);
499 }
500
501
502
503
504 /* delete either message or folder, based on where we are */
505 void
506 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
507 {
508         g_return_if_fail (MODEST_IS_WINDOW(win));
509         
510         /* Check first if the header view has the focus */
511         if (MODEST_IS_MAIN_WINDOW (win)) {
512                 GtkWidget *w;
513                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
514                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
515                 if (gtk_widget_is_focus (w)) {
516                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
517                         return;
518                 }
519         }
520         modest_ui_actions_on_delete_message (action, win);
521 }
522
523
524
525 void
526 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
527 {
528 #ifdef MODEST_PLATFORM_MAEMO
529         modest_osso_save_state();
530 #endif /* MODEST_PLATFORM_MAEMO */
531
532         g_debug ("closing down, clearing %d item(s) from operation queue",
533                  modest_mail_operation_queue_num_elements
534                  (modest_runtime_get_mail_operation_queue()));
535
536         /* cancel all outstanding operations */
537         modest_mail_operation_queue_cancel_all 
538                 (modest_runtime_get_mail_operation_queue());
539         
540         g_debug ("queue has been cleared");
541
542         /* note: when modest-tny-account-store is finalized,
543            it will automatically set all network connections
544            to offline */
545
546         gtk_main_quit ();
547 }
548
549 void
550 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
551 {
552         gboolean ret_value;
553
554         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
555
556 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
557 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
558 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
559 /*              gboolean ret_value; */
560 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
561 /*      } else if (MODEST_IS_WINDOW (win)) { */
562 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
563 /*      } else { */
564 /*              g_return_if_reached (); */
565 /*      } */
566 }
567
568 void
569 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
570 {
571         GtkClipboard *clipboard = NULL;
572         gchar *selection = NULL;
573
574         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
575         selection = gtk_clipboard_wait_for_text (clipboard);
576
577         /* Question: why is the clipboard being used here? 
578          * It doesn't really make a lot of sense. */
579
580         if (selection)
581         {
582                 modest_address_book_add_address (selection);
583                 g_free (selection);
584         }
585 }
586
587 void
588 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
589 {
590         /* This is currently only implemented for Maemo */
591 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
592         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
593                 modest_run_account_setup_wizard (win);
594                 return;
595         } else  {
596                 /* Show the list of accounts: */
597                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
598                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
599                 
600                 /* Don't make this a modal window, because secondary windows will then 
601                  * be unusable, freezing the UI: */
602                 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
603                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
604         }
605 #else
606         GtkWidget *dialog, *label;
607         
608         /* Create the widgets */
609         
610         dialog = gtk_dialog_new_with_buttons ("Message",
611                                               GTK_WINDOW(win),
612                                               GTK_DIALOG_DESTROY_WITH_PARENT,
613                                               GTK_STOCK_OK,
614                                               GTK_RESPONSE_NONE,
615                                               NULL);
616         label = gtk_label_new ("Hello World!");
617         
618         /* Ensure that the dialog box is destroyed when the user responds. */
619         
620         g_signal_connect_swapped (dialog, "response", 
621                                   G_CALLBACK (gtk_widget_destroy),
622                                   dialog);
623         
624         /* Add the label, and show everything we've added to the dialog. */
625         
626         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
627                            label);
628         gtk_widget_show_all (dialog);
629 #endif /* MODEST_PLATFORM_MAEMO */
630 }
631
632 static void
633 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
634 {
635         ModestWindow *main_window = MODEST_WINDOW (user_data);
636         
637         /* Save any changes. */
638         modest_connection_specific_smtp_window_save_server_accounts (
639                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
640                         modest_window_get_active_account (main_window));
641         gtk_widget_destroy (GTK_WIDGET (window));
642 }
643
644
645
646 void
647 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
648 {
649         /* This is currently only implemented for Maemo,
650          * because it requires an API (libconic) to detect different connection 
651          * possiblities.
652          */
653 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
654         
655         /* Create the window if necessary: */
656         const gchar *active_account_name = modest_window_get_active_account (win);
657         
658         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
659          * or show the default account?
660          * If we show the default account then the account name should be shown in 
661          * the window when we show it. */
662         if (!active_account_name) {
663                 g_warning ("%s: No account is active.", __FUNCTION__);
664                 return;
665         }
666                 
667         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
668         modest_connection_specific_smtp_window_fill_with_connections (
669                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
670                 modest_runtime_get_account_mgr(), 
671                 active_account_name);
672
673         /* Show the window: */  
674         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
675         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
676         gtk_widget_show (specific_window);
677     
678         /* Save changes when the window is hidden: */
679         g_signal_connect (specific_window, "hide", 
680                 G_CALLBACK (on_smtp_servers_window_hide), win);
681 #endif /* MODEST_PLATFORM_MAEMO */
682 }
683
684 void
685 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
686 {
687         ModestWindow *msg_win = NULL;
688         TnyMsg *msg = NULL;
689         TnyFolder *folder = NULL;
690         gchar *account_name = NULL;
691         gchar *from_str = NULL;
692 /*      GError *err = NULL; */
693         TnyAccount *account = NULL;
694         ModestWindowMgr *mgr;
695         gchar *signature = NULL, *blank_and_signature = NULL;
696
697         /* if there are no accounts yet, just show the wizard */
698         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
699                         const gboolean created = modest_run_account_setup_wizard (win);
700                         if (!created)
701                                 return;
702         }
703         
704         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
705         if (!account_name)
706                 account_name = g_strdup (modest_window_get_active_account (win));
707         if (!account_name) {
708                 g_printerr ("modest: no account found\n");
709                 goto cleanup;
710         }
711         
712         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
713                                                                        account_name,
714                                                                        TNY_ACCOUNT_TYPE_STORE);
715         if (!account) {
716                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
717                 goto cleanup;
718         }
719
720         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
721         if (!from_str) {
722                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
723                 goto cleanup;
724         }
725
726         gboolean use_signature = FALSE;
727         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
728
729         if (use_signature) {
730                 blank_and_signature = g_strconcat ("\n", signature, NULL);
731         } else {
732                 blank_and_signature = g_strdup ("");
733         }
734
735         g_free (signature);
736
737         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
738         if (!msg) {
739                 g_printerr ("modest: failed to create new msg\n");
740                 goto cleanup;
741         }
742         
743         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
744         if (!folder) {
745                 g_printerr ("modest: failed to find Drafts folder\n");
746                 goto cleanup;
747         }
748         
749
750         /* Create and register edit window */
751         /* This is destroyed by TODO. */
752         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
753         mgr = modest_runtime_get_window_mgr ();
754         modest_window_mgr_register_window (mgr, msg_win);
755
756         if (win)
757                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
758                                               GTK_WINDOW (win));        
759         gtk_widget_show_all (GTK_WIDGET (msg_win));
760
761 cleanup:
762         g_free (account_name);
763         g_free (from_str);
764         g_free (blank_and_signature);
765         if (msg_win)
766                 g_object_unref (msg_win);
767         if (account)
768                 g_object_unref (G_OBJECT(account));
769         if (msg)
770                 g_object_unref (G_OBJECT(msg));
771         if (folder)
772                 g_object_unref (G_OBJECT(folder));
773 }
774
775 gboolean 
776 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
777                                        TnyHeader *header,
778                                        TnyMsg *msg)
779 {
780         ModestMailOperationStatus status;
781
782         /* If there is no message or the operation was not successful */
783         status = modest_mail_operation_get_status (mail_op);
784         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
785
786                 /* Remove the header from the preregistered uids */
787                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
788                                                      header);
789
790                 return FALSE;
791         }
792
793         return TRUE;
794 }
795
796 static void
797 open_msg_cb (ModestMailOperation *mail_op, 
798              TnyHeader *header, 
799              TnyMsg *msg, 
800              gpointer user_data)
801 {
802         ModestWindowMgr *mgr = NULL;
803         ModestWindow *parent_win = NULL;
804         ModestWindow *win = NULL;
805         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
806         gchar *account = NULL;
807         TnyFolder *folder;
808         
809         /* Do nothing if there was any problem with the mail
810            operation. The error will be shown by the error_handler of
811            the mail operation */
812         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
813                 return;
814         }
815
816         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
817         folder = tny_header_get_folder (header);
818
819         /* Mark header as read */
820         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
821
822         /* Get account */
823         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
824         if (!account)
825                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
826         
827         /* Gets folder type (OUTBOX headers will be opened in edit window */
828         if (modest_tny_folder_is_local_folder (folder))
829                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
830
831         /* If the header is in the drafts folder then open the editor,
832            else the message view window */
833         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
834             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
835                 /* we cannot edit without a valid account... */
836                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
837                         const gboolean created = modest_run_account_setup_wizard(parent_win);
838                         if (!created)
839                                 goto cleanup;
840                 }
841                 win = modest_msg_edit_window_new (msg, account, TRUE);
842                 
843         } else {
844                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
845                 
846                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
847                         GtkWidget *header_view;
848                         GtkTreeSelection *sel;
849                         GList *sel_list = NULL;
850                         GtkTreeModel *model;
851                         
852                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
853                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
854
855                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
856                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
857
858                         if (sel_list != NULL) {
859                                 GtkTreeRowReference *row_reference;
860
861                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
862                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
863                                 g_list_free (sel_list);
864                                 
865                                 win = modest_msg_view_window_new_with_header_model (
866                                                 msg, account, (const gchar*) uid,
867                                                 model, row_reference);
868                                 gtk_tree_row_reference_free (row_reference);
869                         } else {
870                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
871                         }
872                 } else {
873                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
874                 }
875                 g_free (uid);
876         }
877         
878         /* Register and show new window */
879         if (win != NULL) {
880                 mgr = modest_runtime_get_window_mgr ();
881                 modest_window_mgr_register_window (mgr, win);
882                 g_object_unref (win);
883                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
884                 gtk_widget_show_all (GTK_WIDGET(win));
885         }
886
887         /* Update toolbar dimming state */
888         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
889                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
890         }
891
892 cleanup:
893         /* Free */
894         g_free(account);
895         g_object_unref (parent_win);
896         g_object_unref (folder);
897 }
898
899 void
900 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
901                                                gpointer user_data)
902 {
903         const GError *error;
904         GObject *win = modest_mail_operation_get_source (mail_op);
905
906         error = modest_mail_operation_get_error (mail_op);
907         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
908  
909         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
910
911                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
912                                                         error->message);
913         } else {
914                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
915                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
916         }
917
918         if (win)
919                 g_object_unref (win);
920 }
921
922 /*
923  * This function is used by both modest_ui_actions_on_open and
924  * modest_ui_actions_on_header_activated. This way we always do the
925  * same when trying to open messages.
926  */
927 static void
928 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
929 {
930         ModestWindowMgr *mgr = NULL;
931         TnyIterator *iter = NULL;
932         ModestMailOperation *mail_op = NULL;
933         TnyList *not_opened_headers = NULL;
934         TnyHeaderFlags flags = 0;
935                 
936         /* Look if we already have a message view for each header. If
937            true, then remove the header from the list of headers to
938            open */
939         mgr = modest_runtime_get_window_mgr ();
940         iter = tny_list_create_iterator (headers);
941         not_opened_headers = tny_simple_list_new ();
942
943         while (!tny_iterator_is_done (iter)) {
944
945                 ModestWindow *window = NULL;
946                 TnyHeader *header = NULL;
947                 gboolean found = FALSE;
948                 
949                 header = TNY_HEADER (tny_iterator_get_current (iter));
950                 if (header)
951                         flags = tny_header_get_flags (header);
952
953                 window = NULL;
954                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
955                 
956                 /* Do not open again the message and present the
957                    window to the user */
958                 if (found) {
959                         if (window)
960                                 gtk_window_present (GTK_WINDOW (window));
961                         else
962                                 /* the header has been registered already, we don't do
963                                  * anything but wait for the window to come up*/
964                                 g_debug ("header %p already registered, waiting for window", header);
965                 } else {
966                         tny_list_append (not_opened_headers, G_OBJECT (header));
967                 }
968
969                 if (header)
970                         g_object_unref (header);
971
972                 tny_iterator_next (iter);
973         }
974         g_object_unref (iter);
975         iter = NULL;
976         
977         /* If some messages would have to be downloaded, ask the user to 
978          * make a connection. It's generally easier to do this here (in the mainloop) 
979          * than later in a thread:
980          */
981         if (tny_list_get_length (not_opened_headers) > 0) {
982                 TnyIterator *iter;
983                 gboolean found = FALSE;
984
985                 iter = tny_list_create_iterator (not_opened_headers);
986                 while (!tny_iterator_is_done (iter) && !found) {
987                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
988                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
989                                 found = TRUE;
990                         else
991                                 tny_iterator_next (iter);
992
993                         g_object_unref (header);
994                 }
995                 g_object_unref (iter);
996
997                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
998                         g_object_unref (not_opened_headers);
999                         return;                 
1000                 }
1001         }
1002         
1003         /* Register the headers before actually creating the windows: */
1004         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1005         while (!tny_iterator_is_done (iter_not_opened)) {
1006                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1007                 if (header) {
1008                         modest_window_mgr_register_header (mgr, header);
1009                         g_object_unref (header);
1010                 }
1011                 
1012                 tny_iterator_next (iter_not_opened);
1013         }
1014         g_object_unref (iter_not_opened);
1015         iter_not_opened = NULL;
1016         
1017         /* Open each message */
1018         if (tny_list_get_length (not_opened_headers) > 0) {
1019                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1020                                                                          G_OBJECT (win), 
1021                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1022                                                                          NULL);
1023                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1024                 if (tny_list_get_length (not_opened_headers) > 1) {
1025                         modest_mail_operation_get_msgs_full (mail_op, 
1026                                                              not_opened_headers, 
1027                                                              open_msg_cb, 
1028                                                              NULL, 
1029                                                              NULL);
1030                 } else {
1031                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1032                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1033                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1034                         g_object_unref (header);
1035                         g_object_unref (iter);
1036                 }
1037                 g_object_unref (mail_op);
1038         }
1039
1040         /* Clean */
1041         if (not_opened_headers != NULL)
1042                 g_object_unref (not_opened_headers);
1043 }
1044
1045 void
1046 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1047 {
1048         TnyList *headers;
1049
1050         /* Get headers */
1051         headers = get_selected_headers (win);
1052         if (!headers)
1053                 return;
1054
1055         /* Open them */
1056         _modest_ui_actions_open (headers, win);
1057
1058         g_object_unref(headers);
1059 }
1060
1061
1062 static void
1063 free_reply_forward_helper (gpointer data)
1064 {
1065         ReplyForwardHelper *helper;
1066
1067         helper = (ReplyForwardHelper *) data;
1068         g_free (helper->account_name);
1069         g_slice_free (ReplyForwardHelper, helper);
1070 }
1071
1072 static void
1073 reply_forward_cb (ModestMailOperation *mail_op, 
1074                   TnyHeader *header, 
1075                   TnyMsg *msg,
1076                   gpointer user_data)
1077 {
1078         TnyMsg *new_msg;
1079         ReplyForwardHelper *rf_helper;
1080         ModestWindow *msg_win = NULL;
1081         ModestEditType edit_type;
1082         gchar *from = NULL;
1083         TnyAccount *account = NULL;
1084         ModestWindowMgr *mgr = NULL;
1085         gchar *signature = NULL;
1086
1087         /* If there was any error. The mail operation could be NULL,
1088            this means that we already have the message downloaded and
1089            that we didn't do a mail operation to retrieve it */
1090         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1091                 return;
1092                         
1093         g_return_if_fail (user_data != NULL);
1094         rf_helper = (ReplyForwardHelper *) user_data;
1095
1096         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1097                                                    rf_helper->account_name);
1098         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1099                                          rf_helper->account_name,
1100                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1101                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1102                                                            rf_helper->account_name,
1103                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1104         }
1105
1106         /* Create reply mail */
1107         switch (rf_helper->action) {
1108         case ACTION_REPLY:
1109                 new_msg = 
1110                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1111                                                          rf_helper->reply_forward_type,
1112                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1113                 break;
1114         case ACTION_REPLY_TO_ALL:
1115                 new_msg = 
1116                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1117                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1118                 edit_type = MODEST_EDIT_TYPE_REPLY;
1119                 break;
1120         case ACTION_FORWARD:
1121                 new_msg = 
1122                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1123                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1124                 break;
1125         default:
1126                 g_return_if_reached ();
1127                 return;
1128         }
1129
1130         g_free (signature);
1131
1132         if (!new_msg) {
1133                 g_printerr ("modest: failed to create message\n");
1134                 goto cleanup;
1135         }
1136
1137         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1138                                                                        rf_helper->account_name,
1139                                                                        TNY_ACCOUNT_TYPE_STORE);
1140         if (!account) {
1141                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1142                 goto cleanup;
1143         }
1144
1145         /* Create and register the windows */
1146         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1147         mgr = modest_runtime_get_window_mgr ();
1148         modest_window_mgr_register_window (mgr, msg_win);
1149
1150         if (rf_helper->parent_window != NULL) {
1151                 gdouble parent_zoom;
1152
1153                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1154                 modest_window_set_zoom (msg_win, parent_zoom);
1155         }
1156
1157         /* Show edit window */
1158         gtk_widget_show_all (GTK_WIDGET (msg_win));
1159
1160 cleanup:
1161         if (msg_win)
1162                 g_object_unref (msg_win);
1163         if (new_msg)
1164                 g_object_unref (G_OBJECT (new_msg));
1165         if (account)
1166                 g_object_unref (G_OBJECT (account));
1167 /*      g_object_unref (msg); */
1168         free_reply_forward_helper (rf_helper);
1169 }
1170
1171 /*
1172  * Checks a list of headers. If any of them are not currently
1173  * downloaded (CACHED) then it asks the user for permission to
1174  * download them.
1175  *
1176  * Returns FALSE if the user does not want to download the
1177  * messages. Returns TRUE if the user allowed the download or if all
1178  * of them are currently downloaded
1179  */
1180 static gboolean
1181 download_uncached_messages (TnyList *header_list, 
1182                             GtkWindow *win)
1183 {
1184         TnyIterator *iter;
1185         gboolean retval;
1186         gint uncached_messages = 0;
1187
1188         iter = tny_list_create_iterator (header_list);
1189         while (!tny_iterator_is_done (iter)) {
1190                 TnyHeader *header;
1191
1192                 header = TNY_HEADER (tny_iterator_get_current (iter));
1193                 if (header) {
1194                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1195                                 uncached_messages ++;
1196                         g_object_unref (header);
1197                 }
1198
1199                 tny_iterator_next (iter);
1200         }
1201         g_object_unref (iter);
1202
1203         /* Ask for user permission to download the messages */
1204         retval = TRUE;
1205         if (uncached_messages > 0) {
1206                 gboolean download = TRUE;
1207                 if (!tny_device_is_online (modest_runtime_get_device())) {
1208                         GtkResponseType response =
1209                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1210                                                                          ngettext("mcen_nc_get_msg",
1211                                                                                   "mcen_nc_get_msgs",
1212                                                                                   uncached_messages));
1213                         if (response == GTK_RESPONSE_CANCEL) download = FALSE;
1214                 }
1215                 if (download) {
1216                         /* If a download will be necessary, make sure that we have a connection: */
1217                         retval = modest_platform_connect_and_wait(win, NULL);   
1218                 } else {
1219                         retval = FALSE;
1220                 }
1221         }
1222         return retval;
1223 }
1224
1225
1226 /*
1227  * Common code for the reply and forward actions
1228  */
1229 static void
1230 reply_forward (ReplyForwardAction action, ModestWindow *win)
1231 {
1232         ModestMailOperation *mail_op = NULL;
1233         TnyList *header_list = NULL;
1234         ReplyForwardHelper *rf_helper = NULL;
1235         guint reply_forward_type;
1236         gboolean continue_download = TRUE;
1237         gboolean do_retrieve = TRUE;
1238         
1239         g_return_if_fail (MODEST_IS_WINDOW(win));
1240
1241         /* we need an account when editing */
1242         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1243                 const gboolean created = modest_run_account_setup_wizard (win);
1244                 if (!created)
1245                         return;
1246         }
1247         
1248         header_list = get_selected_headers (win);
1249         if (!header_list)
1250                 return;
1251
1252         reply_forward_type = 
1253                 modest_conf_get_int (modest_runtime_get_conf (),
1254                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1255                                      NULL);
1256
1257         /* Check that the messages have been previously downloaded */
1258         do_retrieve = (action == ACTION_FORWARD) || (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1259         if (do_retrieve)
1260                 continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
1261         if (!continue_download) {
1262                 g_object_unref (header_list);
1263                 return;
1264         }
1265         
1266         /* We assume that we can only select messages of the
1267            same folder and that we reply all of them from the
1268            same account. In fact the interface currently only
1269            allows single selection */
1270         
1271         /* Fill helpers */
1272         rf_helper = g_slice_new0 (ReplyForwardHelper);
1273         rf_helper->reply_forward_type = reply_forward_type;
1274         rf_helper->action = action;
1275         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1276         
1277         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1278                 rf_helper->parent_window = GTK_WIDGET (win);
1279         if (!rf_helper->account_name)
1280                 rf_helper->account_name =
1281                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1282
1283         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1284                 TnyMsg *msg;
1285                 TnyHeader *header;
1286                 /* Get header and message. Do not free them here, the
1287                    reply_forward_cb must do it */
1288                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1289                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1290                 if (!msg || !header) {
1291                         if (msg)
1292                                 g_object_unref (msg);
1293                         g_printerr ("modest: no message found\n");
1294                         return;
1295                 } else {
1296                         reply_forward_cb (NULL, header, msg, rf_helper);
1297                 }
1298                 if (header)
1299                         g_object_unref (header);
1300         } else {
1301                 TnyHeader *header;
1302                 TnyIterator *iter;
1303
1304                 /* Only reply/forward to one message */
1305                 iter = tny_list_create_iterator (header_list);
1306                 header = TNY_HEADER (tny_iterator_get_current (iter));
1307                 g_object_unref (iter);
1308
1309                 if (header) {
1310                         /* Retrieve messages */
1311                         if (do_retrieve) {
1312                                 mail_op = modest_mail_operation_new_with_error_handling (
1313                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1314                                         G_OBJECT(win),
1315                                         modest_ui_actions_get_msgs_full_error_handler, 
1316                                         NULL);
1317                                 modest_mail_operation_queue_add (
1318                                         modest_runtime_get_mail_operation_queue (), mail_op);
1319                                 
1320                                 modest_mail_operation_get_msg (mail_op,
1321                                                                header,
1322                                                                reply_forward_cb,
1323                                                                rf_helper);
1324                                 /* Clean */
1325                                 g_object_unref(mail_op);
1326                         } else {
1327                                 /* we put a ref here to prevent double unref as the reply
1328                                  * forward callback unrefs the header at its end */
1329                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1330                         }
1331
1332
1333                         g_object_unref (header);
1334                 }
1335
1336         }
1337
1338         /* Free */
1339         g_object_unref (header_list);
1340 }
1341
1342 void
1343 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1344 {
1345         g_return_if_fail (MODEST_IS_WINDOW(win));
1346
1347         reply_forward (ACTION_REPLY, win);
1348 }
1349
1350 void
1351 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1352 {
1353         g_return_if_fail (MODEST_IS_WINDOW(win));
1354
1355         reply_forward (ACTION_FORWARD, win);
1356 }
1357
1358 void
1359 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1360 {
1361         g_return_if_fail (MODEST_IS_WINDOW(win));
1362
1363         reply_forward (ACTION_REPLY_TO_ALL, win);
1364 }
1365
1366 void 
1367 modest_ui_actions_on_next (GtkAction *action, 
1368                            ModestWindow *window)
1369 {
1370         if (MODEST_IS_MAIN_WINDOW (window)) {
1371                 GtkWidget *header_view;
1372
1373                 header_view = modest_main_window_get_child_widget (
1374                                 MODEST_MAIN_WINDOW(window),
1375                                 MODEST_WIDGET_TYPE_HEADER_VIEW);
1376                 if (!header_view)
1377                         return;
1378         
1379                 modest_header_view_select_next (
1380                                 MODEST_HEADER_VIEW(header_view)); 
1381         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1382                 modest_msg_view_window_select_next_message (
1383                                 MODEST_MSG_VIEW_WINDOW (window));
1384         } else {
1385                 g_return_if_reached ();
1386         }
1387 }
1388
1389 void 
1390 modest_ui_actions_on_prev (GtkAction *action, 
1391                            ModestWindow *window)
1392 {
1393         g_return_if_fail (MODEST_IS_WINDOW(window));
1394
1395         if (MODEST_IS_MAIN_WINDOW (window)) {
1396                 GtkWidget *header_view;
1397                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1398                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1399                 if (!header_view)
1400                         return;
1401                 
1402                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1403         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1404                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1405         } else {
1406                 g_return_if_reached ();
1407         }
1408 }
1409
1410 void 
1411 modest_ui_actions_on_sort (GtkAction *action, 
1412                            ModestWindow *window)
1413 {
1414         g_return_if_fail (MODEST_IS_WINDOW(window));
1415
1416         if (MODEST_IS_MAIN_WINDOW (window)) {
1417                 GtkWidget *header_view;
1418                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1419                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1420                 if (!header_view) {
1421                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1422
1423                         return;
1424                 }
1425
1426                 /* Show sorting dialog */
1427                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1428         }
1429 }
1430
1431 static void
1432 new_messages_arrived (ModestMailOperation *self, 
1433                       gint new_messages,
1434                       gpointer user_data)
1435 {
1436         ModestMainWindow *win = NULL;
1437         GtkWidget *folder_view = NULL;
1438         TnyFolderStore *folder = NULL;
1439         gboolean folder_empty = FALSE;
1440
1441         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1442         win = MODEST_MAIN_WINDOW (user_data);
1443
1444         /* Set contents style of headers view */
1445         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1446                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1447                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
1448                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1449                 
1450
1451                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1452                 
1453                 if (!folder_empty)
1454                         modest_main_window_set_contents_style (win,
1455                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1456         }       
1457
1458         /* Notify new messages have been downloaded */
1459         if (new_messages > 0)
1460                 modest_platform_on_new_msg ();
1461 }
1462
1463 /*
1464  * This function performs the send & receive required actions. The
1465  * window is used to create the mail operation. Typically it should
1466  * always be the main window, but we pass it as argument in order to
1467  * be more flexible.
1468  */
1469 void
1470 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1471 {
1472         gchar *acc_name = NULL;
1473         ModestMailOperation *mail_op;
1474
1475         /* If no account name was provided then get the current account, and if
1476            there is no current account then pick the default one: */
1477         if (!account_name) {
1478                 acc_name = g_strdup (modest_window_get_active_account(win));
1479                 if (!acc_name)
1480                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1481                 if (!acc_name) {
1482                         g_printerr ("modest: cannot get default account\n");
1483                         return;
1484                 }
1485         } else {
1486                 acc_name = g_strdup (account_name);
1487         }
1488
1489         /* Set send/receive operation in progress */    
1490         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1491
1492         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1493                                                                  G_OBJECT (win),
1494                                                                  modest_ui_actions_send_receive_error_handler,
1495                                                                  NULL);
1496
1497         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1498                           G_CALLBACK (_on_send_receive_progress_changed), 
1499                           win);
1500
1501         /* Send & receive. */
1502         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1503         /* Receive and then send. The operation is tagged initially as
1504            a receive operation because the account update performs a
1505            receive and then a send. The operation changes its type
1506            internally, so the progress objects will receive the proper
1507            progress information */
1508         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1509         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1510         g_object_unref (G_OBJECT (mail_op));
1511         
1512         /* Free */
1513         g_free (acc_name);
1514 }
1515
1516
1517 static void
1518 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1519                                   ModestWindow *win)
1520 {
1521         TnyTransportAccount *transport_account;
1522         TnySendQueue *send_queue = NULL;
1523         GError *error = NULL;
1524
1525         /* Get transport account */
1526         transport_account =
1527                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1528                                       (modest_runtime_get_account_store(),
1529                                        account_name,
1530                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1531         if (!transport_account) {
1532                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1533                 goto frees;
1534         }
1535
1536         /* Get send queue*/
1537         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1538         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1539                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1540                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1541                              "modest: could not find send queue for account\n");
1542         } else {
1543                 /* Keeep messages in outbox folder */
1544                 tny_send_queue_cancel (send_queue, FALSE, &error);
1545         }       
1546
1547  frees:
1548         if (transport_account != NULL) 
1549                 g_object_unref (G_OBJECT (transport_account));
1550 }
1551
1552 static void
1553 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1554 {
1555         GSList *account_names, *iter;
1556
1557         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1558                                                           TRUE);
1559
1560         iter = account_names;
1561         while (iter) {                  
1562                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1563                 iter = g_slist_next (iter);
1564         }
1565
1566         modest_account_mgr_free_account_names (account_names);
1567         account_names = NULL;
1568 }
1569
1570 void
1571 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1572
1573 {
1574         /* Check if accounts exist */
1575         gboolean accounts_exist = 
1576                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1577         
1578         /* If not, allow the user to create an account before trying to send/receive. */
1579         if (!accounts_exist)
1580                 modest_ui_actions_on_accounts (NULL, win);
1581         
1582         /* Cancel all sending operaitons */     
1583         modest_ui_actions_cancel_send_all (win);
1584 }
1585
1586 /*
1587  * Refreshes all accounts. This function will be used by automatic
1588  * updates
1589  */
1590 void
1591 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1592 {
1593         GSList *account_names, *iter;
1594
1595         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1596                                                           TRUE);
1597
1598         iter = account_names;
1599         while (iter) {                  
1600                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1601                 iter = g_slist_next (iter);
1602         }
1603
1604         modest_account_mgr_free_account_names (account_names);
1605         account_names = NULL;
1606 }
1607
1608 void 
1609 modest_do_refresh_current_folder(ModestWindow *win)
1610 {
1611         /* Refresh currently selected folder. Note that if we only
1612            want to retreive the headers, then the refresh only will
1613            invoke a poke_status over all folders, i.e., only the
1614            total/unread count will be updated */
1615         if (MODEST_IS_MAIN_WINDOW (win)) {
1616                 GtkWidget *header_view, *folder_view;
1617                 TnyFolderStore *folder_store;
1618
1619                 /* Get folder and header view */
1620                 folder_view = 
1621                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1622                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1623
1624                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1625
1626                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1627                         header_view = 
1628                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1629                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1630                 
1631                         /* We do not need to set the contents style
1632                            because it hasn't changed. We also do not
1633                            need to save the widget status. Just force
1634                            a refresh */
1635                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1636                                                        TNY_FOLDER (folder_store),
1637                                                        folder_refreshed_cb,
1638                                                        MODEST_MAIN_WINDOW (win));
1639                 }
1640                 
1641                 if (folder_store)
1642                         g_object_unref (folder_store);
1643         }
1644 }
1645
1646
1647 /*
1648  * Handler of the click on Send&Receive button in the main toolbar
1649  */
1650 void
1651 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1652 {
1653         /* Check if accounts exist */
1654         gboolean accounts_exist = 
1655                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1656         
1657         /* If not, allow the user to create an account before trying to send/receive. */
1658         if (!accounts_exist)
1659                 modest_ui_actions_on_accounts (NULL, win);
1660
1661         modest_do_refresh_current_folder (win);
1662         
1663         /* Refresh the active account */
1664         modest_ui_actions_do_send_receive (NULL, win);
1665 }
1666
1667
1668 void
1669 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1670 {
1671         ModestConf *conf;
1672         GtkWidget *header_view;
1673         
1674         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1675
1676         header_view = modest_main_window_get_child_widget (main_window,
1677                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1678         if (!header_view)
1679                 return;
1680
1681         conf = modest_runtime_get_conf ();
1682         
1683         /* what is saved/restored is depending on the style; thus; we save with
1684          * old style, then update the style, and restore for this new style
1685          */
1686         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1687         
1688         if (modest_header_view_get_style
1689             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1690                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1691                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1692         else
1693                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1694                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1695
1696         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1697                                       MODEST_CONF_HEADER_VIEW_KEY);
1698 }
1699
1700
1701 void 
1702 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1703                                       TnyHeader *header,
1704                                       ModestMainWindow *main_window)
1705 {
1706         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1707         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1708         
1709         /* in the case the folder is empty, show the empty folder message and focus
1710          * folder view */
1711         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1712                 if (modest_header_view_is_empty (header_view)) {
1713                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1714                         GtkWidget *folder_view = 
1715                                 modest_main_window_get_child_widget (main_window,
1716                                                                      MODEST_WIDGET_TYPE_FOLDER_VIEW);
1717                         if (folder != NULL) 
1718                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1719                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1720                         return;
1721                 }
1722         }
1723         /* If no header has been selected then exit */
1724         if (!header)
1725                 return;
1726
1727         /* Update focus */
1728         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1729             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1730
1731         /* Update toolbar dimming state */
1732         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1733 }
1734
1735 void
1736 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1737                                        TnyHeader *header,
1738                                        ModestMainWindow *main_window)
1739 {
1740         TnyList *headers;
1741
1742         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1743         
1744         if (!header)
1745                 return;
1746
1747         headers = tny_simple_list_new ();
1748         tny_list_prepend (headers, G_OBJECT (header));
1749
1750         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1751
1752         g_object_unref (headers);
1753 }
1754
1755 static void
1756 set_active_account_from_tny_account (TnyAccount *account,
1757                                      ModestWindow *window)
1758 {
1759         const gchar *server_acc_name = tny_account_get_id (account);
1760         
1761         /* We need the TnyAccount provided by the
1762            account store because that is the one that
1763            knows the name of the Modest account */
1764         TnyAccount *modest_server_account = modest_server_account = 
1765                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1766                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1767                                                              server_acc_name);
1768         
1769         const gchar *modest_acc_name = 
1770                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1771         modest_window_set_active_account (window, modest_acc_name);
1772         g_object_unref (modest_server_account);
1773 }
1774
1775
1776 static void
1777 folder_refreshed_cb (ModestMailOperation *mail_op, 
1778                      TnyFolder *folder, 
1779                      gpointer user_data)
1780 {
1781         ModestMainWindow *win = NULL;
1782         GtkWidget *header_view;
1783         TnyFolder *current_folder;
1784         gboolean folder_empty = FALSE;
1785         gboolean all_marked_as_deleted = FALSE;
1786
1787         g_return_if_fail (TNY_IS_FOLDER (folder));
1788
1789         win = MODEST_MAIN_WINDOW (user_data);
1790         header_view = 
1791                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1792
1793         if (header_view) {
1794                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1795                 if (current_folder != NULL && folder != current_folder) {
1796                         return;
1797                 }
1798         }
1799
1800         /* Check if folder is empty and set headers view contents style */
1801         folder_empty = (tny_folder_get_all_count (folder) == 0);
1802         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1803         folder_empty = folder_empty || all_marked_as_deleted ;
1804         if (folder_empty) {
1805
1806         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1807                 modest_main_window_set_contents_style (win,
1808                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1809         } else {
1810                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1811         }
1812 }
1813
1814 void 
1815 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1816                                                TnyFolderStore *folder_store, 
1817                                                gboolean selected,
1818                                                ModestMainWindow *main_window)
1819 {
1820         ModestConf *conf;
1821         GtkWidget *header_view;
1822
1823         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1824
1825         header_view = modest_main_window_get_child_widget(main_window,
1826                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1827         if (!header_view)
1828                 return;
1829         
1830         conf = modest_runtime_get_conf ();
1831
1832         if (TNY_IS_ACCOUNT (folder_store)) {
1833                 if (selected) {
1834                         /* Update active account */
1835                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1836                         /* Show account details */
1837                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1838                 }
1839         } else {
1840                 if (TNY_IS_FOLDER (folder_store) && selected) {
1841                         
1842                         /* Update the active account */
1843                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1844                         if (account) {
1845                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1846                                 g_object_unref (account);
1847                                 account = NULL;
1848                         }
1849
1850                         /* Set the header style by default, it could
1851                            be changed later by the refresh callback to
1852                            empty */
1853                         modest_main_window_set_contents_style (main_window, 
1854                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1855
1856                         /* Set folder on header view. This function
1857                            will call tny_folder_refresh_async so we
1858                            pass a callback that will be called when
1859                            finished. We use that callback to set the
1860                            empty view if there are no messages */
1861                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1862                                                        TNY_FOLDER (folder_store),
1863                                                        folder_refreshed_cb,
1864                                                        main_window);
1865                         
1866                         /* Restore configuration. We need to do this
1867                            *after* the set_folder because the widget
1868                            memory asks the header view about its
1869                            folder  */
1870                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1871                                                       G_OBJECT(header_view),
1872                                                       MODEST_CONF_HEADER_VIEW_KEY);
1873                 } else {
1874                         /* Update the active account */
1875                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1876                         /* Save only if we're seeing headers */
1877                         if (modest_main_window_get_contents_style (main_window) ==
1878                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1879                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1880                                                            MODEST_CONF_HEADER_VIEW_KEY);
1881                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1882                 }
1883         }
1884
1885         /* Update toolbar dimming state */
1886         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1887 }
1888
1889 void 
1890 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1891                                      ModestWindow *win)
1892 {
1893         GtkWidget *dialog;
1894         gchar *txt, *item;
1895         gboolean online;
1896
1897         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1898         
1899         online = tny_device_is_online (modest_runtime_get_device());
1900
1901         if (online) {
1902                 /* already online -- the item is simply not there... */
1903                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1904                                                  GTK_DIALOG_MODAL,
1905                                                  GTK_MESSAGE_WARNING,
1906                                                  GTK_BUTTONS_OK,
1907                                                  _("The %s you selected cannot be found"),
1908                                                  item);
1909                 gtk_dialog_run (GTK_DIALOG(dialog));
1910         } else {
1911                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1912                                                       GTK_WINDOW (win),
1913                                                       GTK_DIALOG_MODAL,
1914                                                       GTK_STOCK_CANCEL,
1915                                                       GTK_RESPONSE_REJECT,
1916                                                       GTK_STOCK_OK,
1917                                                       GTK_RESPONSE_ACCEPT,
1918                                                       NULL);
1919                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1920                                          "Do you want to get online?"), item);
1921                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1922                                     gtk_label_new (txt), FALSE, FALSE, 0);
1923                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1924                 g_free (txt);
1925
1926                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1927                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1928                         /* TODO: Comment about why is this commented out: */
1929                         /* modest_platform_connect_and_wait (); */
1930                 }
1931         }
1932         gtk_widget_destroy (dialog);
1933 }
1934
1935 void
1936 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1937                                      ModestWindow *win)
1938 {
1939         /* g_message ("%s %s", __FUNCTION__, link); */
1940 }       
1941
1942
1943 void
1944 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1945                                         ModestWindow *win)
1946 {
1947         modest_platform_activate_uri (link);
1948 }
1949
1950 void
1951 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1952                                           ModestWindow *win)
1953 {
1954         modest_platform_show_uri_popup (link);
1955 }
1956
1957 void
1958 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1959                                              ModestWindow *win)
1960 {
1961         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1962 }
1963
1964 void
1965 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1966                                           const gchar *address,
1967                                           ModestWindow *win)
1968 {
1969         /* g_message ("%s %s", __FUNCTION__, address); */
1970 }
1971
1972 void
1973 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1974 {
1975         TnyTransportAccount *transport_account;
1976         ModestMailOperation *mail_operation;
1977         MsgData *data;
1978         gchar *account_name, *from;
1979         ModestAccountMgr *account_mgr;
1980         gchar *info_text = NULL;
1981
1982         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1983         
1984         data = modest_msg_edit_window_get_msg_data (edit_window);
1985
1986         account_mgr = modest_runtime_get_account_mgr();
1987         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1988         if (!account_name) 
1989                 account_name = modest_account_mgr_get_default_account (account_mgr);
1990         if (!account_name) {
1991                 g_printerr ("modest: no account found\n");
1992                 modest_msg_edit_window_free_msg_data (edit_window, data);
1993                 return;
1994         }
1995
1996         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1997                 account_name = g_strdup (data->account_name);
1998         }
1999
2000         transport_account =
2001                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2002                                       (modest_runtime_get_account_store(),
2003                                        account_name,
2004                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2005         if (!transport_account) {
2006                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2007                 g_free (account_name);
2008                 modest_msg_edit_window_free_msg_data (edit_window, data);
2009                 return;
2010         }
2011         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2012
2013         /* Create the mail operation */         
2014         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2015         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2016
2017         modest_mail_operation_save_to_drafts (mail_operation,
2018                                               transport_account,
2019                                               data->draft_msg,
2020                                               edit_window,
2021                                               from,
2022                                               data->to, 
2023                                               data->cc, 
2024                                               data->bcc,
2025                                               data->subject, 
2026                                               data->plain_body, 
2027                                               data->html_body,
2028                                               data->attachments,
2029                                               data->priority_flags);
2030         /* Frees */
2031         g_free (from);
2032         g_free (account_name);
2033         g_object_unref (G_OBJECT (transport_account));
2034         g_object_unref (G_OBJECT (mail_operation));
2035
2036         modest_msg_edit_window_free_msg_data (edit_window, data);
2037
2038         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2039         modest_platform_information_banner (NULL, NULL, info_text);
2040         g_free (info_text);
2041 }
2042
2043 /* For instance, when clicking the Send toolbar button when editing a message: */
2044 void
2045 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2046 {
2047         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2048
2049         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2050                 return;
2051         
2052         /* Offer the connection dialog, if necessary: */        
2053         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2054                 return;
2055         
2056         /* FIXME: Code added just for testing. The final version will
2057            use the send queue provided by tinymail and some
2058            classifier */
2059         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2060         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2061         if (!account_name) 
2062                 account_name = modest_account_mgr_get_default_account (account_mgr);
2063                 
2064         if (!account_name) {
2065                 /* Run account setup wizard */
2066                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2067                 if (!created)
2068                         return;
2069         }
2070         
2071         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2072
2073         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2074                 account_name = g_strdup (data->account_name);
2075         }
2076         
2077         /* Get the currently-active transport account for this modest account: */
2078         TnyTransportAccount *transport_account =
2079                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2080                                       (modest_runtime_get_account_store(),
2081                                        account_name));
2082         if (!transport_account) {
2083                 /* Run account setup wizard */
2084                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2085                 if (!created)
2086                         return;
2087         }
2088         
2089         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2090
2091 /*      modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent")); */
2092
2093         /* Create the mail operation */
2094         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2095         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2096
2097         modest_mail_operation_send_new_mail (mail_operation,
2098                                              transport_account,
2099                                              data->draft_msg,
2100                                              from,
2101                                              data->to, 
2102                                              data->cc, 
2103                                              data->bcc,
2104                                              data->subject, 
2105                                              data->plain_body, 
2106                                              data->html_body,
2107                                              data->attachments,
2108                                              data->priority_flags);
2109                                              
2110         /* Free data: */
2111         g_free (from);
2112         g_free (account_name);
2113         g_object_unref (G_OBJECT (transport_account));
2114         g_object_unref (G_OBJECT (mail_operation));
2115
2116         modest_msg_edit_window_free_msg_data (edit_window, data);
2117         modest_msg_edit_window_set_sent (edit_window, TRUE);
2118
2119         /* Save settings and close the window: */
2120         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2121 }
2122
2123 void 
2124 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2125                                   ModestMsgEditWindow *window)
2126 {
2127         ModestMsgEditFormatState *format_state = NULL;
2128
2129         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2130         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2131
2132         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2133                 return;
2134
2135         format_state = modest_msg_edit_window_get_format_state (window);
2136         g_return_if_fail (format_state != NULL);
2137
2138         format_state->bold = gtk_toggle_action_get_active (action);
2139         modest_msg_edit_window_set_format_state (window, format_state);
2140         g_free (format_state);
2141         
2142 }
2143
2144 void 
2145 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2146                                      ModestMsgEditWindow *window)
2147 {
2148         ModestMsgEditFormatState *format_state = NULL;
2149
2150         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2151         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2152
2153         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2154                 return;
2155
2156         format_state = modest_msg_edit_window_get_format_state (window);
2157         g_return_if_fail (format_state != NULL);
2158
2159         format_state->italics = gtk_toggle_action_get_active (action);
2160         modest_msg_edit_window_set_format_state (window, format_state);
2161         g_free (format_state);
2162         
2163 }
2164
2165 void 
2166 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2167                                      ModestMsgEditWindow *window)
2168 {
2169         ModestMsgEditFormatState *format_state = NULL;
2170
2171         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2172         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2173
2174         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2175                 return;
2176
2177         format_state = modest_msg_edit_window_get_format_state (window);
2178         g_return_if_fail (format_state != NULL);
2179
2180         format_state->bullet = gtk_toggle_action_get_active (action);
2181         modest_msg_edit_window_set_format_state (window, format_state);
2182         g_free (format_state);
2183         
2184 }
2185
2186 void 
2187 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2188                                      GtkRadioAction *selected,
2189                                      ModestMsgEditWindow *window)
2190 {
2191         ModestMsgEditFormatState *format_state = NULL;
2192         GtkJustification value;
2193
2194         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2195
2196         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2197                 return;
2198
2199         value = gtk_radio_action_get_current_value (selected);
2200
2201         format_state = modest_msg_edit_window_get_format_state (window);
2202         g_return_if_fail (format_state != NULL);
2203
2204         format_state->justification = value;
2205         modest_msg_edit_window_set_format_state (window, format_state);
2206         g_free (format_state);
2207 }
2208
2209 void 
2210 modest_ui_actions_on_select_editor_color (GtkAction *action,
2211                                           ModestMsgEditWindow *window)
2212 {
2213         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2214         g_return_if_fail (GTK_IS_ACTION (action));
2215
2216         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2217                 return;
2218
2219         modest_msg_edit_window_select_color (window);
2220 }
2221
2222 void 
2223 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2224                                                      ModestMsgEditWindow *window)
2225 {
2226         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2227         g_return_if_fail (GTK_IS_ACTION (action));
2228
2229         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2230                 return;
2231
2232         modest_msg_edit_window_select_background_color (window);
2233 }
2234
2235 void 
2236 modest_ui_actions_on_insert_image (GtkAction *action,
2237                                    ModestMsgEditWindow *window)
2238 {
2239         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2240         g_return_if_fail (GTK_IS_ACTION (action));
2241
2242         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2243                 return;
2244
2245         modest_msg_edit_window_insert_image (window);
2246 }
2247
2248 void 
2249 modest_ui_actions_on_attach_file (GtkAction *action,
2250                                   ModestMsgEditWindow *window)
2251 {
2252         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2253         g_return_if_fail (GTK_IS_ACTION (action));
2254
2255         modest_msg_edit_window_offer_attach_file (window);
2256 }
2257
2258 void 
2259 modest_ui_actions_on_remove_attachments (GtkAction *action,
2260                                          ModestMsgEditWindow *window)
2261 {
2262         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2263         g_return_if_fail (GTK_IS_ACTION (action));
2264
2265         modest_msg_edit_window_remove_attachments (window, NULL);
2266 }
2267
2268 static void
2269 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2270                                             gpointer user_data)
2271 {
2272         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2273         const GError *error = modest_mail_operation_get_error (mail_op);
2274
2275         if(error)
2276         {
2277                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2278                                                     modest_mail_operation_get_error (mail_op)->message);
2279         }
2280 }
2281
2282 static void
2283 modest_ui_actions_create_folder(GtkWidget *parent_window,
2284                                 GtkWidget *folder_view)
2285 {
2286         TnyFolderStore *parent_folder;
2287
2288         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2289         
2290         if (parent_folder) {
2291                 gboolean finished = FALSE;
2292                 gint result;
2293                 gchar *folder_name = NULL, *suggested_name = NULL;
2294                 const gchar *proto_str = NULL;
2295                 TnyAccount *account;
2296
2297                 if (TNY_IS_ACCOUNT (parent_folder))
2298                         account = g_object_ref (parent_folder);
2299                 else
2300                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2301                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2302
2303                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2304                     MODEST_PROTOCOL_STORE_POP) {
2305                         finished = TRUE;
2306                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2307                 }
2308                 g_object_unref (account);
2309
2310                 /* Run the new folder dialog */
2311                 while (!finished) {
2312                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2313                                                                         parent_folder,
2314                                                                         suggested_name,
2315                                                                         &folder_name);
2316
2317                         g_free (suggested_name);
2318                         suggested_name = NULL;
2319
2320                         if (result == GTK_RESPONSE_REJECT) {
2321                                 finished = TRUE;
2322                         } else {
2323                                 ModestMailOperation *mail_op;
2324                                 TnyFolder *new_folder = NULL;
2325
2326                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2327                                                                                           G_OBJECT(parent_window),
2328                                                                                           modest_ui_actions_new_folder_error_handler,
2329                                                                                           parent_window);
2330
2331                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2332                                                                  mail_op);
2333                                 new_folder = modest_mail_operation_create_folder (mail_op,
2334                                                                                   parent_folder,
2335                                                                                   (const gchar *) folder_name);
2336                                 if (new_folder) {
2337                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2338                                                                           new_folder, TRUE);
2339
2340                                         g_object_unref (new_folder);
2341                                         finished = TRUE;
2342                                 }
2343                                 g_object_unref (mail_op);
2344                         }
2345
2346                         suggested_name = folder_name;
2347                         folder_name = NULL;
2348                 }
2349
2350                 g_object_unref (parent_folder);
2351         }
2352 }
2353
2354 void 
2355 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2356 {
2357         GtkWidget *folder_view;
2358         
2359         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2360
2361         folder_view = modest_main_window_get_child_widget (main_window,
2362                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2363         if (!folder_view)
2364                 return;
2365
2366         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2367 }
2368
2369 static void
2370 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2371                                                gpointer user_data)
2372 {
2373         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2374         const GError *error = NULL;
2375         const gchar *message = NULL;
2376         
2377         /* Get error message */
2378         error = modest_mail_operation_get_error (mail_op);
2379         if (error != NULL && error->message != NULL) {
2380                 message = error->message;
2381         } else {
2382                 message = _("!!! FIXME: Unable to rename");
2383         }
2384         
2385         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2386                                             message);
2387 }
2388
2389 void 
2390 modest_ui_actions_on_rename_folder (GtkAction *action,
2391                                      ModestMainWindow *main_window)
2392 {
2393         TnyFolderStore *folder;
2394         GtkWidget *folder_view;
2395         GtkWidget *header_view; 
2396
2397         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2398
2399         folder_view = modest_main_window_get_child_widget (main_window,
2400                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2401         if (!folder_view)
2402                 return;
2403
2404         header_view = modest_main_window_get_child_widget (main_window,
2405                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2406         
2407         if (!header_view)
2408                 return;
2409
2410         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2411         if (!folder)
2412                 return;
2413
2414         /* Offer the connection dialog if necessary: */
2415         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2416                 g_object_unref (G_OBJECT (folder));
2417                 return;
2418         }
2419
2420         
2421         if (TNY_IS_FOLDER (folder)) {
2422                 gchar *folder_name;
2423                 gint response;
2424                 const gchar *current_name;
2425                 TnyFolderStore *parent;
2426
2427                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2428                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2429                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2430                                                                      parent, current_name, 
2431                                                                      &folder_name);
2432                 g_object_unref (parent);
2433
2434                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2435                         ModestMailOperation *mail_op;
2436
2437                         mail_op = 
2438                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2439                                                                                G_OBJECT(main_window),
2440                                                                                modest_ui_actions_rename_folder_error_handler,
2441                                                                                main_window);
2442                         
2443
2444                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2445                                                          mail_op);
2446
2447                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2448                         
2449                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2450                                                           TNY_FOLDER(folder), TRUE);
2451
2452                         modest_header_view_clear ((ModestHeaderView *) header_view);
2453  
2454                         modest_mail_operation_rename_folder (mail_op,
2455                                                              TNY_FOLDER (folder),
2456                                                              (const gchar *) folder_name);
2457
2458                         g_object_unref (mail_op);
2459                         g_free (folder_name);
2460                 }
2461         }
2462         g_object_unref (folder);
2463 }
2464
2465 static void
2466 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2467                                                gpointer user_data)
2468 {
2469         GObject *win = modest_mail_operation_get_source (mail_op);
2470
2471         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2472                                                 _("mail_in_ui_folder_delete_error"));
2473         g_object_unref (win);
2474 }
2475
2476 static void
2477 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2478 {
2479         TnyFolderStore *folder;
2480         GtkWidget *folder_view;
2481         gint response;
2482         gchar *message;
2483         
2484         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2485
2486         folder_view = modest_main_window_get_child_widget (main_window,
2487                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2488         if (!folder_view)
2489                 return;
2490
2491         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2492
2493         /* Show an error if it's an account */
2494         if (!TNY_IS_FOLDER (folder)) {
2495                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2496                                                         _("mail_in_ui_folder_delete_error"));
2497                 g_object_unref (G_OBJECT (folder));
2498                 return ;
2499         }
2500
2501         /* Offer the connection dialog if necessary: */
2502         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2503                 g_object_unref (G_OBJECT (folder));
2504                 return;
2505         }
2506
2507         /* Ask the user */      
2508         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2509                                     tny_folder_get_name (TNY_FOLDER (folder)));
2510         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2511                                                             (const gchar *) message);
2512         g_free (message);
2513
2514         if (response == GTK_RESPONSE_OK) {
2515                 ModestMailOperation *mail_op = 
2516                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2517                                                                        G_OBJECT(main_window),
2518                                                                        modest_ui_actions_delete_folder_error_handler,
2519                                                                        NULL);
2520
2521                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2522                                                  mail_op);
2523                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2524                 g_object_unref (G_OBJECT (mail_op));
2525         }
2526
2527         g_object_unref (G_OBJECT (folder));
2528 }
2529
2530 void 
2531 modest_ui_actions_on_delete_folder (GtkAction *action,
2532                                      ModestMainWindow *main_window)
2533 {
2534         GtkWidget *folder_view;
2535         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2536
2537         delete_folder (main_window, FALSE);
2538         folder_view = modest_main_window_get_child_widget (main_window,
2539                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2540         if (!folder_view)
2541                 return;
2542         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2543 }
2544
2545 void 
2546 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2547 {
2548         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2549         
2550         delete_folder (main_window, TRUE);
2551 }
2552
2553
2554 static void
2555 show_error (GtkWidget *parent_widget, const gchar* text)
2556 {
2557         hildon_banner_show_information(parent_widget, NULL, text);
2558         
2559 #if 0
2560         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2561         /*
2562           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2563           (GtkDialogFlags)0,
2564           GTK_MESSAGE_ERROR,
2565           GTK_BUTTONS_OK,
2566           text ));
2567         */
2568                  
2569         gtk_dialog_run (dialog);
2570         gtk_widget_destroy (GTK_WIDGET (dialog));
2571 #endif
2572 }
2573
2574 void
2575 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2576                                          const gchar* server_account_name,
2577                                          gchar **username,
2578                                          gchar **password, 
2579                                          gboolean *cancel, 
2580                                          gboolean *remember,
2581                                          ModestMainWindow *main_window)
2582 {
2583         g_return_if_fail(server_account_name);
2584         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2585         
2586         /* Initalize output parameters: */
2587         if (cancel)
2588                 *cancel = FALSE;
2589                 
2590         if (remember)
2591                 *remember = TRUE;
2592                 
2593 #ifdef MODEST_PLATFORM_MAEMO
2594         /* Maemo uses a different (awkward) button order,
2595          * It should probably just use gtk_alternative_dialog_button_order ().
2596          */
2597         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2598                                               NULL,
2599                                               GTK_DIALOG_MODAL,
2600                                               GTK_STOCK_OK,
2601                                               GTK_RESPONSE_ACCEPT,
2602                                               GTK_STOCK_CANCEL,
2603                                               GTK_RESPONSE_REJECT,
2604                                               NULL);
2605 #else
2606         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2607                                               NULL,
2608                                               GTK_DIALOG_MODAL,
2609                                               GTK_STOCK_CANCEL,
2610                                               GTK_RESPONSE_REJECT,
2611                                               GTK_STOCK_OK,
2612                                               GTK_RESPONSE_ACCEPT,
2613                                               NULL);
2614 #endif /* MODEST_PLATFORM_MAEMO */
2615
2616         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2617         
2618         gchar *server_name = modest_server_account_get_hostname (
2619                 modest_runtime_get_account_mgr(), server_account_name);
2620         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2621                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2622                 *cancel = TRUE;
2623                 return;
2624         }
2625         
2626         /* This causes a warning because the logical ID has no %s in it, 
2627          * though the translation does, but there is not much we can do about that: */
2628         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2629         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2630                             FALSE, FALSE, 0);
2631         g_free (txt);
2632         g_free (server_name);
2633         server_name = NULL;
2634
2635         /* username: */
2636         gchar *initial_username = modest_server_account_get_username (
2637                 modest_runtime_get_account_mgr(), server_account_name);
2638         
2639         GtkWidget *entry_username = gtk_entry_new ();
2640         if (initial_username)
2641                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2642         /* Dim this if a connection has ever succeeded with this username,
2643          * as per the UI spec: */
2644         const gboolean username_known = 
2645                 modest_server_account_get_username_has_succeeded(
2646                         modest_runtime_get_account_mgr(), server_account_name);
2647         gtk_widget_set_sensitive (entry_username, !username_known);
2648         
2649 #ifdef MODEST_PLATFORM_MAEMO
2650         /* Auto-capitalization is the default, so let's turn it off: */
2651         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2652         
2653         /* Create a size group to be used by all captions.
2654          * Note that HildonCaption does not create a default size group if we do not specify one.
2655          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2656         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2657         
2658         GtkWidget *caption = hildon_caption_new (sizegroup, 
2659                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2660         gtk_widget_show (entry_username);
2661         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2662                 FALSE, FALSE, MODEST_MARGIN_HALF);
2663         gtk_widget_show (caption);
2664 #else 
2665         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2666                             TRUE, FALSE, 0);
2667 #endif /* MODEST_PLATFORM_MAEMO */      
2668                             
2669         /* password: */
2670         GtkWidget *entry_password = gtk_entry_new ();
2671         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2672         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2673         
2674 #ifdef MODEST_PLATFORM_MAEMO
2675         /* Auto-capitalization is the default, so let's turn it off: */
2676         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2677                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2678         
2679         caption = hildon_caption_new (sizegroup, 
2680                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2681         gtk_widget_show (entry_password);
2682         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2683                 FALSE, FALSE, MODEST_MARGIN_HALF);
2684         gtk_widget_show (caption);
2685         g_object_unref (sizegroup);
2686 #else 
2687         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2688                             TRUE, FALSE, 0);
2689 #endif /* MODEST_PLATFORM_MAEMO */      
2690                                 
2691 /* This is not in the Maemo UI spec:
2692         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2693         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2694                             TRUE, FALSE, 0);
2695 */
2696
2697         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2698         
2699         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2700                 if (username) {
2701                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2702                         
2703                         modest_server_account_set_username (
2704                                  modest_runtime_get_account_mgr(), server_account_name, 
2705                                  *username);
2706                                  
2707                         const gboolean username_was_changed = 
2708                                 (strcmp (*username, initial_username) != 0);
2709                         if (username_was_changed) {
2710                                 g_warning ("%s: tinymail does not yet support changing the "
2711                                         "username in the get_password() callback.\n", __FUNCTION__);
2712                         }
2713                 }
2714                         
2715                 if (password) {
2716                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2717                         
2718                         /* We do not save the password in the configuration, 
2719                          * because this function is only called for passwords that should 
2720                          * not be remembered:
2721                         modest_server_account_set_password (
2722                                  modest_runtime_get_account_mgr(), server_account_name, 
2723                                  *password);
2724                         */
2725                 }
2726                 
2727                 if (cancel)
2728                         *cancel   = FALSE;
2729                         
2730         } else {
2731                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2732                 
2733                 if (username)
2734                         *username = NULL;
2735                         
2736                 if (password)
2737                         *password = NULL;
2738                         
2739                 if (cancel)
2740                         *cancel   = TRUE;
2741         }
2742
2743 /* This is not in the Maemo UI spec:
2744         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2745                 *remember = TRUE;
2746         else
2747                 *remember = FALSE;
2748 */
2749
2750         gtk_widget_destroy (dialog);
2751         
2752         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2753 }
2754
2755 void
2756 modest_ui_actions_on_cut (GtkAction *action,
2757                           ModestWindow *window)
2758 {
2759         GtkWidget *focused_widget;
2760         GtkClipboard *clipboard;
2761
2762         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2763         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2764         if (GTK_IS_EDITABLE (focused_widget)) {
2765                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2766                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2767                 gtk_clipboard_store (clipboard);
2768         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2769                 GtkTextBuffer *buffer;
2770
2771                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2772                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2773                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2774                 gtk_clipboard_store (clipboard);
2775         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2776                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2777         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2778                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2779         }
2780 }
2781
2782 void
2783 modest_ui_actions_on_copy (GtkAction *action,
2784                            ModestWindow *window)
2785 {
2786         GtkClipboard *clipboard;
2787         GtkWidget *focused_widget;
2788
2789         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2790         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2791
2792         if (GTK_IS_LABEL (focused_widget)) {
2793                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2794                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2795                 gtk_clipboard_store (clipboard);
2796         } else if (GTK_IS_EDITABLE (focused_widget)) {
2797                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2798                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2799                 gtk_clipboard_store (clipboard);
2800         } else if (GTK_IS_HTML (focused_widget)) {
2801                 gtk_html_copy (GTK_HTML (focused_widget));
2802                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2803                 gtk_clipboard_store (clipboard);
2804         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2805                 GtkTextBuffer *buffer;
2806                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2807                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2808                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2809                 gtk_clipboard_store (clipboard);
2810         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2811                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2812                 TnyIterator *iter = tny_list_create_iterator (header_list);
2813                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2814                 
2815                 gboolean ask = FALSE;
2816                 if (header) {
2817                         TnyFolder *folder = tny_header_get_folder (header);
2818                         TnyAccount *account = tny_folder_get_account (folder);
2819                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2820                         /* If it's POP then ask */
2821                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2822                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2823                         g_object_unref (account);
2824                         g_object_unref (folder);
2825                         g_object_unref (header);
2826                 }
2827
2828                 g_object_unref (iter);
2829                 
2830                 /* Check that the messages have been previously downloaded */
2831                 gboolean continue_download = TRUE;
2832                 if (ask)
2833                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2834                 if (continue_download)
2835                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2836                 g_object_unref (header_list);
2837         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2838                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2839         }    
2840
2841         /* Show information banner */
2842         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2843         
2844 }
2845
2846 void
2847 modest_ui_actions_on_undo (GtkAction *action,
2848                            ModestWindow *window)
2849 {
2850         ModestEmailClipboard *clipboard = NULL;
2851
2852         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2853                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2854         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2855                 /* Clear clipboard source */
2856                 clipboard = modest_runtime_get_email_clipboard ();
2857                 modest_email_clipboard_clear (clipboard);               
2858         }
2859         else {
2860                 g_return_if_reached ();
2861         }
2862 }
2863
2864 void
2865 modest_ui_actions_on_redo (GtkAction *action,
2866                            ModestWindow *window)
2867 {
2868         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2869                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2870         }
2871         else {
2872                 g_return_if_reached ();
2873         }
2874 }
2875
2876
2877 static void
2878 paste_msgs_cb (const GObject *object, gpointer user_data)
2879 {
2880         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2881         g_return_if_fail (GTK_IS_WIDGET (user_data));
2882         
2883         /* destroy information note */
2884         gtk_widget_destroy (GTK_WIDGET(user_data));
2885 }
2886
2887 static void
2888 paste_as_attachment_free (gpointer data)
2889 {
2890         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2891
2892         gtk_widget_destroy (helper->banner);
2893         g_object_unref (helper->banner);
2894         g_free (helper);
2895 }
2896
2897 static void
2898 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2899                             TnyHeader *header,
2900                             TnyMsg *msg,
2901                             gpointer userdata)
2902 {
2903         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2904         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2905
2906         if (msg == NULL)
2907                 return;
2908
2909         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2910         
2911 }
2912
2913 void
2914 modest_ui_actions_on_paste (GtkAction *action,
2915                             ModestWindow *window)
2916 {
2917         GtkWidget *focused_widget = NULL;
2918         GtkWidget *inf_note = NULL;
2919         ModestMailOperation *mail_op = NULL;
2920
2921         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2922         if (GTK_IS_EDITABLE (focused_widget)) {
2923                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2924         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2925                 ModestEmailClipboard *e_clipboard = NULL;
2926                 e_clipboard = modest_runtime_get_email_clipboard ();
2927                 if (modest_email_clipboard_cleared (e_clipboard)) {
2928                         GtkTextBuffer *buffer;
2929                         GtkClipboard *clipboard;
2930
2931                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2932                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2933                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2934                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2935                         ModestMailOperation *mail_op;
2936                         TnyFolder *src_folder;
2937                         TnyList *data;
2938                         gboolean delete;
2939                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2940                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2941                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2942                                                                            _CS("ckct_nw_pasting"));
2943                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2944                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2945                                                              G_OBJECT (window));
2946                         if (helper->banner != NULL) {
2947                                 g_object_ref (G_OBJECT (helper->banner));
2948                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2949                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2950                         }
2951
2952                         if (data != NULL) {
2953                                 modest_mail_operation_get_msgs_full (mail_op, 
2954                                                                      data,
2955                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
2956                                                                      helper,
2957                                                                      paste_as_attachment_free);
2958                         }
2959                 }
2960         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2961                 ModestEmailClipboard *clipboard = NULL;
2962                 TnyFolder *src_folder = NULL;
2963                 TnyFolderStore *folder_store = NULL;
2964                 TnyList *data = NULL;           
2965                 gboolean delete = FALSE;
2966                 
2967                 /* Check clipboard source */
2968                 clipboard = modest_runtime_get_email_clipboard ();
2969                 if (modest_email_clipboard_cleared (clipboard)) 
2970                         return;
2971                 
2972                 /* Get elements to paste */
2973                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2974
2975                 /* Create a new mail operation */
2976                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2977                 
2978                 /* Get destination folder */
2979                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2980
2981                 /* transfer messages  */
2982                 if (data != NULL) {
2983                         gint response = 0;
2984
2985                         /* Ask for user confirmation */
2986                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
2987                                                               TNY_FOLDER (folder_store), 
2988                                                               delete,
2989                                                               data);
2990                         
2991                         if (response == GTK_RESPONSE_OK) {
2992                                 /* Launch notification */
2993                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2994                                                                              _CS("ckct_nw_pasting"));
2995                                 if (inf_note != NULL)  {
2996                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2997                                         gtk_widget_show (GTK_WIDGET(inf_note));
2998                                 }
2999
3000                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3001                                 modest_mail_operation_xfer_msgs (mail_op, 
3002                                                                  data,
3003                                                                  TNY_FOLDER (folder_store),
3004                                                                  delete,
3005                                                                  paste_msgs_cb,
3006                                                                  inf_note);                             
3007                         } else {
3008                                 g_object_unref (mail_op);
3009                         }
3010                         
3011                 } else if (src_folder != NULL) {                        
3012                         /* Launch notification */
3013                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3014                                                                      _CS("ckct_nw_pasting"));
3015                         if (inf_note != NULL)  {
3016                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3017                                 gtk_widget_show (GTK_WIDGET(inf_note));
3018                         }
3019                         
3020                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3021                         modest_mail_operation_xfer_folder (mail_op, 
3022                                                            src_folder,
3023                                                            folder_store,
3024                                                            delete,
3025                                                            paste_msgs_cb,
3026                                                            inf_note);
3027                 }
3028
3029                 /* Free */
3030                 if (data != NULL) 
3031                         g_object_unref (data);
3032                 if (src_folder != NULL) 
3033                         g_object_unref (src_folder);
3034                 if (folder_store != NULL) 
3035                         g_object_unref (folder_store);
3036         }
3037 }
3038
3039
3040 void
3041 modest_ui_actions_on_select_all (GtkAction *action,
3042                                  ModestWindow *window)
3043 {
3044         GtkWidget *focused_widget;
3045
3046         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3047         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3048                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3049         } else if (GTK_IS_LABEL (focused_widget)) {
3050                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3051         } else if (GTK_IS_EDITABLE (focused_widget)) {
3052                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3053         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3054                 GtkTextBuffer *buffer;
3055                 GtkTextIter start, end;
3056
3057                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3058                 gtk_text_buffer_get_start_iter (buffer, &start);
3059                 gtk_text_buffer_get_end_iter (buffer, &end);
3060                 gtk_text_buffer_select_range (buffer, &start, &end);
3061         } else if (GTK_IS_HTML (focused_widget)) {
3062                 gtk_html_select_all (GTK_HTML (focused_widget));
3063         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3064                 GtkWidget *header_view = focused_widget;
3065                 GtkTreeSelection *selection = NULL;
3066                 
3067                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
3068                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3069                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3070                                 
3071                 /* Select all messages */
3072                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3073                 gtk_tree_selection_select_all (selection);
3074
3075                 /* Set focuse on header view */
3076                 gtk_widget_grab_focus (header_view);
3077         }
3078
3079 }
3080
3081 void
3082 modest_ui_actions_on_mark_as_read (GtkAction *action,
3083                                    ModestWindow *window)
3084 {       
3085         g_return_if_fail (MODEST_IS_WINDOW(window));
3086                 
3087         /* Mark each header as read */
3088         do_headers_action (window, headers_action_mark_as_read, NULL);
3089 }
3090
3091 void
3092 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3093                                      ModestWindow *window)
3094 {       
3095         g_return_if_fail (MODEST_IS_WINDOW(window));
3096                 
3097         /* Mark each header as read */
3098         do_headers_action (window, headers_action_mark_as_unread, NULL);
3099 }
3100
3101 void
3102 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3103                                   GtkRadioAction *selected,
3104                                   ModestWindow *window)
3105 {
3106         gint value;
3107
3108         value = gtk_radio_action_get_current_value (selected);
3109         if (MODEST_IS_WINDOW (window)) {
3110                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3111         }
3112 }
3113
3114 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3115                                                         GtkRadioAction *selected,
3116                                                         ModestWindow *window)
3117 {
3118         TnyHeaderFlags flags;
3119         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3120
3121         flags = gtk_radio_action_get_current_value (selected);
3122         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3123 }
3124
3125 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3126                                                            GtkRadioAction *selected,
3127                                                            ModestWindow *window)
3128 {
3129         gint file_format;
3130
3131         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3132
3133         file_format = gtk_radio_action_get_current_value (selected);
3134         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3135 }
3136
3137
3138 void     
3139 modest_ui_actions_on_zoom_plus (GtkAction *action,
3140                                 ModestWindow *window)
3141 {
3142         g_return_if_fail (MODEST_IS_WINDOW (window));
3143
3144         modest_window_zoom_plus (MODEST_WINDOW (window));
3145 }
3146
3147 void     
3148 modest_ui_actions_on_zoom_minus (GtkAction *action,
3149                                  ModestWindow *window)
3150 {
3151         g_return_if_fail (MODEST_IS_WINDOW (window));
3152
3153         modest_window_zoom_minus (MODEST_WINDOW (window));
3154 }
3155
3156 void     
3157 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3158                                            ModestWindow *window)
3159 {
3160         ModestWindowMgr *mgr;
3161         gboolean fullscreen, active;
3162         g_return_if_fail (MODEST_IS_WINDOW (window));
3163
3164         mgr = modest_runtime_get_window_mgr ();
3165
3166         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3167         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3168
3169         if (active != fullscreen) {
3170                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3171                 gtk_window_present (GTK_WINDOW (window));
3172         }
3173 }
3174
3175 void
3176 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3177                                         ModestWindow *window)
3178 {
3179         ModestWindowMgr *mgr;
3180         gboolean fullscreen;
3181
3182         g_return_if_fail (MODEST_IS_WINDOW (window));
3183
3184         mgr = modest_runtime_get_window_mgr ();
3185         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3186         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3187
3188         gtk_window_present (GTK_WINDOW (window));
3189 }
3190
3191 /* 
3192  * Used by modest_ui_actions_on_details to call do_headers_action 
3193  */
3194 static void
3195 headers_action_show_details (TnyHeader *header, 
3196                              ModestWindow *window,
3197                              gpointer user_data)
3198
3199 {
3200         GtkWidget *dialog;
3201         
3202         /* Create dialog */
3203         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3204
3205         /* Run dialog */
3206         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3207         gtk_widget_show_all (dialog);
3208         gtk_dialog_run (GTK_DIALOG (dialog));
3209
3210         gtk_widget_destroy (dialog);
3211 }
3212
3213 /*
3214  * Show the folder details in a ModestDetailsDialog widget
3215  */
3216 static void