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