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