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