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