* Partially fixes NB#63588, it works but we still need to find a proper solution...
[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)
2412                 g_return_if_reached ();
2413
2414         switch (error->code) {
2415         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2416                 message = _CS("ckdg_ib_folder_already_exists");
2417                 break;
2418         default:
2419                 g_return_if_reached ();
2420         }
2421
2422         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2423 }
2424
2425 void 
2426 modest_ui_actions_on_rename_folder (GtkAction *action,
2427                                      ModestMainWindow *main_window)
2428 {
2429         TnyFolderStore *folder;
2430         GtkWidget *folder_view;
2431         GtkWidget *header_view; 
2432
2433         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2434
2435         folder_view = modest_main_window_get_child_widget (main_window,
2436                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2437         if (!folder_view)
2438                 return;
2439
2440         header_view = modest_main_window_get_child_widget (main_window,
2441                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2442         
2443         if (!header_view)
2444                 return;
2445
2446         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2447         if (!folder)
2448                 return;
2449
2450         /* Offer the connection dialog if necessary: */
2451         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2452                 g_object_unref (G_OBJECT (folder));
2453                 return;
2454         }
2455
2456         
2457         if (TNY_IS_FOLDER (folder)) {
2458                 gchar *folder_name;
2459                 gint response;
2460                 const gchar *current_name;
2461                 TnyFolderStore *parent;
2462
2463                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2464                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2465                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2466                                                                      parent, current_name, 
2467                                                                      &folder_name);
2468                 g_object_unref (parent);
2469
2470                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2471                         ModestMailOperation *mail_op;
2472                         GtkTreeSelection *sel = NULL;
2473
2474                         mail_op = 
2475                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2476                                                                                G_OBJECT(main_window),
2477                                                                                modest_ui_actions_rename_folder_error_handler,
2478                                                                                main_window);
2479                         
2480
2481                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2482                                                          mail_op);
2483
2484                         /* Clear the headers view */
2485                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2486                         gtk_tree_selection_unselect_all (sel);
2487
2488                         /* Select *after* the changes */
2489                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2490                                                           TNY_FOLDER(folder), TRUE);
2491
2492                         modest_mail_operation_rename_folder (mail_op,
2493                                                              TNY_FOLDER (folder),
2494                                                              (const gchar *) folder_name);
2495
2496                         g_object_unref (mail_op);
2497                         g_free (folder_name);
2498                 }
2499         }
2500         g_object_unref (folder);
2501 }
2502
2503 static void
2504 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2505                                                gpointer user_data)
2506 {
2507         GObject *win = modest_mail_operation_get_source (mail_op);
2508
2509         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2510                                                 _("mail_in_ui_folder_delete_error"));
2511         g_object_unref (win);
2512 }
2513
2514 static void
2515 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2516 {
2517         TnyFolderStore *folder;
2518         GtkWidget *folder_view;
2519         gint response;
2520         gchar *message;
2521         
2522         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2523
2524         folder_view = modest_main_window_get_child_widget (main_window,
2525                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2526         if (!folder_view)
2527                 return;
2528
2529         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2530
2531         /* Show an error if it's an account */
2532         if (!TNY_IS_FOLDER (folder)) {
2533                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2534                                                         _("mail_in_ui_folder_delete_error"));
2535                 g_object_unref (G_OBJECT (folder));
2536                 return ;
2537         }
2538
2539         /* Offer the connection dialog if necessary: */
2540         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2541                 g_object_unref (G_OBJECT (folder));
2542                 return;
2543         }
2544
2545         /* Ask the user */      
2546         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2547                                     tny_folder_get_name (TNY_FOLDER (folder)));
2548         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2549                                                             (const gchar *) message);
2550         g_free (message);
2551
2552         if (response == GTK_RESPONSE_OK) {
2553                 ModestMailOperation *mail_op;
2554                 GtkTreeSelection *sel;
2555
2556                 /* Unselect the folder before deleting it to free the headers */
2557                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2558                 gtk_tree_selection_unselect_all (sel);
2559
2560                 /* Create the mail operation */
2561                 mail_op =
2562                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2563                                                                        G_OBJECT(main_window),
2564                                                                        modest_ui_actions_delete_folder_error_handler,
2565                                                                        NULL);
2566
2567                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2568                                                  mail_op);
2569                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2570                 g_object_unref (G_OBJECT (mail_op));
2571         }
2572
2573         g_object_unref (G_OBJECT (folder));
2574 }
2575
2576 void 
2577 modest_ui_actions_on_delete_folder (GtkAction *action,
2578                                      ModestMainWindow *main_window)
2579 {
2580         GtkWidget *folder_view;
2581         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2582
2583         delete_folder (main_window, FALSE);
2584         folder_view = modest_main_window_get_child_widget (main_window,
2585                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2586         if (!folder_view)
2587                 return;
2588         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2589 }
2590
2591 void 
2592 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2593 {
2594         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2595         
2596         delete_folder (main_window, TRUE);
2597 }
2598
2599
2600 static void
2601 show_error (GtkWidget *parent_widget, const gchar* text)
2602 {
2603         hildon_banner_show_information(parent_widget, NULL, text);
2604         
2605 #if 0
2606         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2607         /*
2608           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2609           (GtkDialogFlags)0,
2610           GTK_MESSAGE_ERROR,
2611           GTK_BUTTONS_OK,
2612           text ));
2613         */
2614                  
2615         gtk_dialog_run (dialog);
2616         gtk_widget_destroy (GTK_WIDGET (dialog));
2617 #endif
2618 }
2619
2620 void
2621 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2622                                          const gchar* server_account_name,
2623                                          gchar **username,
2624                                          gchar **password, 
2625                                          gboolean *cancel, 
2626                                          gboolean *remember,
2627                                          ModestMainWindow *main_window)
2628 {
2629         g_return_if_fail(server_account_name);
2630         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2631         
2632         /* Initalize output parameters: */
2633         if (cancel)
2634                 *cancel = FALSE;
2635                 
2636         if (remember)
2637                 *remember = TRUE;
2638                 
2639 #ifdef MODEST_PLATFORM_MAEMO
2640         /* Maemo uses a different (awkward) button order,
2641          * It should probably just use gtk_alternative_dialog_button_order ().
2642          */
2643         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2644                                               NULL,
2645                                               GTK_DIALOG_MODAL,
2646                                               _("mcen_bd_dialog_ok"),
2647                                               GTK_RESPONSE_ACCEPT,
2648                                               _("mcen_bd_dialog_cancel"),
2649                                               GTK_RESPONSE_REJECT,
2650                                               NULL);
2651 #else
2652         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2653                                               NULL,
2654                                               GTK_DIALOG_MODAL,
2655                                               GTK_STOCK_CANCEL,
2656                                               GTK_RESPONSE_REJECT,
2657                                               GTK_STOCK_OK,
2658                                               GTK_RESPONSE_ACCEPT,
2659                                               NULL);
2660 #endif /* MODEST_PLATFORM_MAEMO */
2661
2662         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2663         
2664         gchar *server_name = modest_server_account_get_hostname (
2665                 modest_runtime_get_account_mgr(), server_account_name);
2666         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2667                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2668                 *cancel = TRUE;
2669                 return;
2670         }
2671         
2672         /* This causes a warning because the logical ID has no %s in it, 
2673          * though the translation does, but there is not much we can do about that: */
2674         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2675         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2676                             FALSE, FALSE, 0);
2677         g_free (txt);
2678         g_free (server_name);
2679         server_name = NULL;
2680
2681         /* username: */
2682         gchar *initial_username = modest_server_account_get_username (
2683                 modest_runtime_get_account_mgr(), server_account_name);
2684         
2685         GtkWidget *entry_username = gtk_entry_new ();
2686         if (initial_username)
2687                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2688         /* Dim this if a connection has ever succeeded with this username,
2689          * as per the UI spec: */
2690         const gboolean username_known = 
2691                 modest_server_account_get_username_has_succeeded(
2692                         modest_runtime_get_account_mgr(), server_account_name);
2693         gtk_widget_set_sensitive (entry_username, !username_known);
2694         
2695 #ifdef MODEST_PLATFORM_MAEMO
2696         /* Auto-capitalization is the default, so let's turn it off: */
2697         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2698         
2699         /* Create a size group to be used by all captions.
2700          * Note that HildonCaption does not create a default size group if we do not specify one.
2701          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2702         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2703         
2704         GtkWidget *caption = hildon_caption_new (sizegroup, 
2705                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2706         gtk_widget_show (entry_username);
2707         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2708                 FALSE, FALSE, MODEST_MARGIN_HALF);
2709         gtk_widget_show (caption);
2710 #else 
2711         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2712                             TRUE, FALSE, 0);
2713 #endif /* MODEST_PLATFORM_MAEMO */      
2714                             
2715         /* password: */
2716         GtkWidget *entry_password = gtk_entry_new ();
2717         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2718         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2719         
2720 #ifdef MODEST_PLATFORM_MAEMO
2721         /* Auto-capitalization is the default, so let's turn it off: */
2722         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2723                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2724         
2725         caption = hildon_caption_new (sizegroup, 
2726                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2727         gtk_widget_show (entry_password);
2728         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2729                 FALSE, FALSE, MODEST_MARGIN_HALF);
2730         gtk_widget_show (caption);
2731         g_object_unref (sizegroup);
2732 #else 
2733         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2734                             TRUE, FALSE, 0);
2735 #endif /* MODEST_PLATFORM_MAEMO */      
2736                                 
2737 /* This is not in the Maemo UI spec:
2738         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2739         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2740                             TRUE, FALSE, 0);
2741 */
2742
2743         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2744         
2745         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2746                 if (username) {
2747                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2748                         
2749                         modest_server_account_set_username (
2750                                  modest_runtime_get_account_mgr(), server_account_name, 
2751                                  *username);
2752                                  
2753                         const gboolean username_was_changed = 
2754                                 (strcmp (*username, initial_username) != 0);
2755                         if (username_was_changed) {
2756                                 g_warning ("%s: tinymail does not yet support changing the "
2757                                         "username in the get_password() callback.\n", __FUNCTION__);
2758                         }
2759                 }
2760                         
2761                 if (password) {
2762                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2763                         
2764                         /* We do not save the password in the configuration, 
2765                          * because this function is only called for passwords that should 
2766                          * not be remembered:
2767                         modest_server_account_set_password (
2768                                  modest_runtime_get_account_mgr(), server_account_name, 
2769                                  *password);
2770                         */
2771                 }
2772                 
2773                 if (cancel)
2774                         *cancel   = FALSE;
2775                         
2776         } else {
2777                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2778                 
2779                 if (username)
2780                         *username = NULL;
2781                         
2782                 if (password)
2783                         *password = NULL;
2784                         
2785                 if (cancel)
2786                         *cancel   = TRUE;
2787         }
2788
2789 /* This is not in the Maemo UI spec:
2790         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2791                 *remember = TRUE;
2792         else
2793                 *remember = FALSE;
2794 */
2795
2796         gtk_widget_destroy (dialog);
2797         
2798         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2799 }
2800
2801 void
2802 modest_ui_actions_on_cut (GtkAction *action,
2803                           ModestWindow *window)
2804 {
2805         GtkWidget *focused_widget;
2806         GtkClipboard *clipboard;
2807
2808         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2809         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2810         if (GTK_IS_EDITABLE (focused_widget)) {
2811                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2812                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2813                 gtk_clipboard_store (clipboard);
2814         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2815                 GtkTextBuffer *buffer;
2816
2817                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2818                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2819                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2820                 gtk_clipboard_store (clipboard);
2821         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2822                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2823         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2824                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2825         }
2826 }
2827
2828 void
2829 modest_ui_actions_on_copy (GtkAction *action,
2830                            ModestWindow *window)
2831 {
2832         GtkClipboard *clipboard;
2833         GtkWidget *focused_widget;
2834
2835         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2836         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2837
2838         if (GTK_IS_LABEL (focused_widget)) {
2839                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2840                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2841                 gtk_clipboard_store (clipboard);
2842         } else if (GTK_IS_EDITABLE (focused_widget)) {
2843                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2844                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2845                 gtk_clipboard_store (clipboard);
2846         } else if (GTK_IS_HTML (focused_widget)) {
2847                 gtk_html_copy (GTK_HTML (focused_widget));
2848                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2849                 gtk_clipboard_store (clipboard);
2850         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2851                 GtkTextBuffer *buffer;
2852                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2853                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2854                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2855                 gtk_clipboard_store (clipboard);
2856         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2857                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2858                 TnyIterator *iter = tny_list_create_iterator (header_list);
2859                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2860                 
2861                 gboolean ask = FALSE;
2862                 if (header) {
2863                         TnyFolder *folder = tny_header_get_folder (header);
2864                         TnyAccount *account = tny_folder_get_account (folder);
2865                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2866                         /* If it's POP then ask */
2867                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2868                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2869                         g_object_unref (account);
2870                         g_object_unref (folder);
2871                         g_object_unref (header);
2872                 }
2873
2874                 g_object_unref (iter);
2875                 
2876                 /* Check that the messages have been previously downloaded */
2877                 gboolean continue_download = TRUE;
2878                 if (ask)
2879                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2880                 if (continue_download)
2881                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2882                 g_object_unref (header_list);
2883         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2884                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2885         }    
2886
2887         /* Show information banner */
2888         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2889         
2890 }
2891
2892 void
2893 modest_ui_actions_on_undo (GtkAction *action,
2894                            ModestWindow *window)
2895 {
2896         ModestEmailClipboard *clipboard = NULL;
2897
2898         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2899                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2900         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2901                 /* Clear clipboard source */
2902                 clipboard = modest_runtime_get_email_clipboard ();
2903                 modest_email_clipboard_clear (clipboard);               
2904         }
2905         else {
2906                 g_return_if_reached ();
2907         }
2908 }
2909
2910 void
2911 modest_ui_actions_on_redo (GtkAction *action,
2912                            ModestWindow *window)
2913 {
2914         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2915                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2916         }
2917         else {
2918                 g_return_if_reached ();
2919         }
2920 }
2921
2922
2923 static void
2924 paste_msgs_cb (const GObject *object, gpointer user_data)
2925 {
2926         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2927         g_return_if_fail (GTK_IS_WIDGET (user_data));
2928         
2929         /* destroy information note */
2930         gtk_widget_destroy (GTK_WIDGET(user_data));
2931 }
2932
2933 static void
2934 paste_as_attachment_free (gpointer data)
2935 {
2936         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2937
2938         gtk_widget_destroy (helper->banner);
2939         g_object_unref (helper->banner);
2940         g_free (helper);
2941 }
2942
2943 static void
2944 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2945                             TnyHeader *header,
2946                             TnyMsg *msg,
2947                             gpointer userdata)
2948 {
2949         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2950         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2951
2952         if (msg == NULL)
2953                 return;
2954
2955         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2956         
2957 }
2958
2959 void
2960 modest_ui_actions_on_paste (GtkAction *action,
2961                             ModestWindow *window)
2962 {
2963         GtkWidget *focused_widget = NULL;
2964         GtkWidget *inf_note = NULL;
2965         ModestMailOperation *mail_op = NULL;
2966
2967         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2968         if (GTK_IS_EDITABLE (focused_widget)) {
2969                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2970         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2971                 ModestEmailClipboard *e_clipboard = NULL;
2972                 e_clipboard = modest_runtime_get_email_clipboard ();
2973                 if (modest_email_clipboard_cleared (e_clipboard)) {
2974                         GtkTextBuffer *buffer;
2975                         GtkClipboard *clipboard;
2976
2977                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2978                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2979                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2980                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2981                         ModestMailOperation *mail_op;
2982                         TnyFolder *src_folder;
2983                         TnyList *data;
2984                         gboolean delete;
2985                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2986                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2987                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2988                                                                            _CS("ckct_nw_pasting"));
2989                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2990                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2991                                                              G_OBJECT (window));
2992                         if (helper->banner != NULL) {
2993                                 g_object_ref (G_OBJECT (helper->banner));
2994                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2995                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2996                         }
2997
2998                         if (data != NULL) {
2999                                 modest_mail_operation_get_msgs_full (mail_op, 
3000                                                                      data,
3001                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3002                                                                      helper,
3003                                                                      paste_as_attachment_free);
3004                         }
3005                 }
3006         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3007                 ModestEmailClipboard *clipboard = NULL;
3008                 TnyFolder *src_folder = NULL;
3009                 TnyFolderStore *folder_store = NULL;
3010                 TnyList *data = NULL;           
3011                 gboolean delete = FALSE;
3012                 
3013                 /* Check clipboard source */
3014                 clipboard = modest_runtime_get_email_clipboard ();
3015                 if (modest_email_clipboard_cleared (clipboard)) 
3016                         return;
3017                 
3018                 /* Get elements to paste */
3019                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3020
3021                 /* Create a new mail operation */
3022                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3023                 
3024                 /* Get destination folder */
3025                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3026
3027                 /* transfer messages  */
3028                 if (data != NULL) {
3029                         gint response = 0;
3030
3031                         /* Ask for user confirmation */
3032                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3033                                                               TNY_FOLDER (folder_store), 
3034                                                               delete,
3035                                                               data);
3036                         
3037                         if (response == GTK_RESPONSE_OK) {
3038                                 /* Launch notification */
3039                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3040                                                                              _CS("ckct_nw_pasting"));
3041                                 if (inf_note != NULL)  {
3042                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3043                                         gtk_widget_show (GTK_WIDGET(inf_note));
3044                                 }
3045
3046                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3047                                 modest_mail_operation_xfer_msgs (mail_op, 
3048                                                                  data,
3049                                                                  TNY_FOLDER (folder_store),
3050                                                                  delete,
3051                                                                  paste_msgs_cb,
3052                                                                  inf_note);                             
3053                         } else {
3054                                 g_object_unref (mail_op);
3055                         }
3056                         
3057                 } else if (src_folder != NULL) {                        
3058                         /* Launch notification */
3059                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3060                                                                      _CS("ckct_nw_pasting"));
3061                         if (inf_note != NULL)  {
3062                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3063                                 gtk_widget_show (GTK_WIDGET(inf_note));
3064                         }
3065                         
3066                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3067                         modest_mail_operation_xfer_folder (mail_op, 
3068                                                            src_folder,
3069                                                            folder_store,
3070                                                            delete,
3071                                                            paste_msgs_cb,
3072                                                            inf_note);
3073                 }
3074
3075                 /* Free */
3076                 if (data != NULL) 
3077                         g_object_unref (data);
3078                 if (src_folder != NULL) 
3079                         g_object_unref (src_folder);
3080                 if (folder_store != NULL) 
3081                         g_object_unref (folder_store);
3082         }
3083 }
3084
3085
3086 void
3087 modest_ui_actions_on_select_all (GtkAction *action,
3088                                  ModestWindow *window)
3089 {
3090         GtkWidget *focused_widget;
3091
3092         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3093         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3094                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3095         } else if (GTK_IS_LABEL (focused_widget)) {
3096                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3097         } else if (GTK_IS_EDITABLE (focused_widget)) {
3098                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3099         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3100                 GtkTextBuffer *buffer;
3101                 GtkTextIter start, end;
3102
3103                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3104                 gtk_text_buffer_get_start_iter (buffer, &start);
3105                 gtk_text_buffer_get_end_iter (buffer, &end);
3106                 gtk_text_buffer_select_range (buffer, &start, &end);
3107         } else if (GTK_IS_HTML (focused_widget)) {
3108                 gtk_html_select_all (GTK_HTML (focused_widget));
3109         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3110                 GtkWidget *header_view = focused_widget;
3111                 GtkTreeSelection *selection = NULL;
3112                 
3113                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
3114                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3115                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3116                                 
3117                 /* Select all messages */
3118                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3119                 gtk_tree_selection_select_all (selection);
3120
3121                 /* Set focuse on header view */
3122                 gtk_widget_grab_focus (header_view);
3123         }
3124
3125 }
3126
3127 void
3128 modest_ui_actions_on_mark_as_read (GtkAction *action,
3129                                    ModestWindow *window)
3130 {       
3131         g_return_if_fail (MODEST_IS_WINDOW(window));
3132                 
3133         /* Mark each header as read */
3134         do_headers_action (window, headers_action_mark_as_read, NULL);
3135 }
3136
3137 void
3138 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3139                                      ModestWindow *window)
3140 {       
3141         g_return_if_fail (MODEST_IS_WINDOW(window));
3142                 
3143         /* Mark each header as read */
3144         do_headers_action (window, headers_action_mark_as_unread, NULL);
3145 }
3146
3147 void
3148 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3149                                   GtkRadioAction *selected,
3150                                   ModestWindow *window)
3151 {
3152         gint value;
3153
3154         value = gtk_radio_action_get_current_value (selected);
3155         if (MODEST_IS_WINDOW (window)) {
3156                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3157         }
3158 }
3159
3160 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3161                                                         GtkRadioAction *selected,
3162                                                         ModestWindow *window)
3163 {
3164         TnyHeaderFlags flags;
3165         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3166
3167         flags = gtk_radio_action_get_current_value (selected);
3168         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3169 }
3170
3171 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3172                                                            GtkRadioAction *selected,
3173                                                            ModestWindow *window)
3174 {
3175         gint file_format;
3176
3177         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3178
3179         file_format = gtk_radio_action_get_current_value (selected);
3180         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3181 }
3182
3183
3184 void     
3185 modest_ui_actions_on_zoom_plus (GtkAction *action,
3186                                 ModestWindow *window)
3187 {
3188         g_return_if_fail (MODEST_IS_WINDOW (window));
3189
3190         modest_window_zoom_plus (MODEST_WINDOW (window));
3191 }
3192
3193 void     
3194 modest_ui_actions_on_zoom_minus (GtkAction *action,
3195                                  ModestWindow *window)
3196 {
3197         g_return_if_fail (MODEST_IS_WINDOW (window));
3198
3199         modest_window_zoom_minus (MODEST_WINDOW (window));
3200 }
3201
3202 void     
3203 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3204                                            ModestWindow *window)
3205 {
3206         ModestWindowMgr *mgr;
3207         gboolean fullscreen, active;
3208         g_return_if_fail (MODEST_IS_WINDOW (window));
3209
3210         mgr = modest_runtime_get_window_mgr ();
3211
3212         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3213         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3214
3215         if (active != fullscreen) {
3216                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3217                 gtk_window_present (GTK_WINDOW (window));
3218         }
3219 }
3220
3221 void
3222 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3223                                         ModestWindow *window)
3224 {
3225         ModestWindowMgr *mgr;
3226         gboolean fullscreen;
3227
3228         g_return_if_fail (MODEST_IS_WINDOW (window));
3229
3230         mgr = modest_runtime_get_window_mgr ();
3231         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3232         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3233
3234         gtk_window_present (GTK_WINDOW (window));
3235 }
3236
3237 /* 
3238  * Used by modest_ui_actions_on_details to call do_headers_action 
3239  */
3240 static void
3241 headers_action_show_details (TnyHeader *header, 
3242                              ModestWindow *window,
3243                              gpointer user_data)
3244
3245 {
3246         GtkWidget *dialog;
3247         
3248         /* Create dialog */
3249         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3250
3251         /* Run dialog */
3252         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3253         gtk_widget_show_all (dialog);
3254         gtk_dialog_run (GTK_DIALOG (dialog));
3255
3256         gtk_widget_destroy (dialog);
3257 }
3258
3259 /*
3260  * Show the folder details in a ModestDetailsDialog widget
3261  */
3262 static void
3263 show_folder_details (TnyFolder *folder, 
3264                      GtkWindow *window)
3265 {
3266         GtkWidget *dialog;
3267         
3268         /* Create dialog */
3269         dialog = modest_details_dialog_new_with_folder (window, folder);
3270
3271         /* Run dialog */
3272         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3273         gtk_widget_show_all (dialog);
3274         gtk_dialog_run (GTK_DIALOG (dialog));
3275
3276         gtk_widget_destroy (dialog);
3277 }
3278
3279 /*
3280  * Show the header details in a ModestDetailsDialog widget
3281  */
3282 void     
3283 modest_ui_actions_on_details (GtkAction *action, 
3284                               ModestWindow *win)
3285 {
3286         TnyList * headers_list;
3287         TnyIterator *iter;
3288         TnyHeader *header;              
3289
3290         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3291                 TnyMsg *msg;
3292
3293                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3294                 if (!msg)
3295                         return;
3296                 g_object_unref (msg);           
3297
3298                 headers_list = get_selected_headers (win);
3299                 if (!headers_list)
3300                         return;
3301
3302                 iter = tny_list_create_iterator (headers_list);
3303
3304                 header = TNY_HEADER (tny_iterator_get_current (iter));
3305                 if (header) {
3306                         headers_action_show_details (header, win, NULL);
3307                         g_object_unref (header);
3308                 }
3309
3310                 g_object_unref (iter);
3311                 g_object_unref (headers_list);
3312
3313         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3314                 GtkWidget *folder_view, *header_view;
3315
3316                 /* Check which widget has the focus */
3317                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3318                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3319                 if (gtk_widget_is_focus (folder_view)) {
3320                         TnyFolderStore *folder_store
3321                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3322                         if (!folder_store) {
3323                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3324                                 return; 
3325                         }
3326                         /* Show only when it's a folder */
3327                         /* This function should not be called for account items, 
3328                          * because we dim the menu item for them. */
3329                         if (TNY_IS_FOLDER (folder_store)) {
3330                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3331                         }
3332
3333                         g_object_unref (folder_store);
3334
3335                 } else {
3336                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3337                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3338                         /* Show details of each header */
3339                         do_headers_action (win, headers_action_show_details, header_view);
3340                 }
3341         }
3342 }
3343
3344 void     
3345 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3346                                      ModestMsgEditWindow *window)
3347 {
3348         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3349
3350         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3351 }
3352
3353 void     
3354 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3355                                       ModestMsgEditWindow *window)
3356 {
3357         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3358
3359         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3360 }
3361
3362 void
3363 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3364                                        ModestMainWindow *main_window)
3365 {
3366         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3367
3368         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3369                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3370         else
3371                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3372 }
3373
3374 void 
3375 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3376                                      ModestWindow *window)
3377 {
3378         gboolean active, fullscreen = FALSE;
3379         ModestWindowMgr *mgr;
3380
3381         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3382
3383         /* Check if we want to toggle the toolbar vuew in fullscreen
3384            or normal mode */
3385         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3386                      "ViewShowToolbarFullScreen")) {
3387                 fullscreen = TRUE;
3388         }
3389
3390         /* Toggle toolbar */
3391         mgr = modest_runtime_get_window_mgr ();
3392         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3393 }
3394
3395 void     
3396 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3397                                            ModestMsgEditWindow *window)
3398 {
3399         modest_msg_edit_window_select_font (window);
3400 }
3401
3402 void
3403 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3404                                                   const gchar *display_name,
3405                                                   GtkWindow *window)
3406 {
3407         /* Do not change the application name if the widget has not
3408            the focus. This callback could be called even if the folder
3409            view has not the focus, because the handled signal could be
3410            emitted when the folder view is redrawn */
3411         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3412                 if (display_name)
3413                         gtk_window_set_title (window, display_name);
3414                 else
3415                         gtk_window_set_title (window, " ");
3416         }
3417 }
3418
3419 void
3420 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3421 {
3422         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3423         modest_msg_edit_window_select_contacts (window);
3424 }
3425
3426 void
3427 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3428 {
3429         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3430         modest_msg_edit_window_check_names (window, FALSE);
3431 }
3432
3433 static void
3434 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3435 {
3436         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3437                                          GTK_WIDGET (user_data));
3438 }
3439
3440 static GtkWidget*
3441 create_move_to_dialog (GtkWindow *win,
3442                        GtkWidget *folder_view,
3443                        GtkWidget **tree_view)
3444 {
3445         GtkWidget *dialog, *scroll;
3446         GtkWidget *new_button;
3447
3448         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3449                                               GTK_WINDOW (win),
3450                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3451                                               NULL);
3452
3453         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3454         /* We do this manually so GTK+ does not associate a response ID for
3455          * the button. */
3456         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3457         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3458         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3459
3460         /* Create scrolled window */
3461         scroll = gtk_scrolled_window_new (NULL, NULL);
3462         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3463                                          GTK_POLICY_AUTOMATIC,
3464                                          GTK_POLICY_AUTOMATIC);
3465
3466         /* Create folder view */
3467         *tree_view = modest_platform_create_folder_view (NULL);
3468
3469         g_signal_connect (G_OBJECT (new_button), 
3470                           "clicked", 
3471                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3472                           *tree_view);
3473
3474         /* It could happen that we're trying to move a message from a
3475            window (msg window for example) after the main window was
3476            closed, so we can not just get the model of the folder
3477            view */
3478         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3479                 const gchar *visible_id = NULL;
3480
3481                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3482                                                MODEST_FOLDER_VIEW(*tree_view));
3483
3484                 visible_id = 
3485                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3486
3487                 /* Show the same account than the one that is shown in the main window */
3488                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3489                                                                              visible_id);
3490         } else {
3491                 const gchar *active_account_name = NULL;
3492                 ModestAccountMgr *mgr = NULL;
3493                 ModestAccountData *acc_data = NULL;
3494
3495                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3496                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3497
3498                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3499                 mgr = modest_runtime_get_account_mgr ();
3500                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3501
3502                 /* Set the new visible & active account */
3503                 if (acc_data && acc_data->store_account) { 
3504                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3505                                                                                      acc_data->store_account->account_name);
3506                         modest_account_mgr_free_account_data (mgr, acc_data);
3507                 }
3508         }
3509
3510         /* Hide special folders */
3511         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3512         
3513         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3514
3515         /* Add scroll to dialog */
3516         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3517                             scroll, TRUE, TRUE, 0);
3518
3519         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3520         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3521
3522         return dialog;
3523 }
3524
3525 /*
3526  * Returns TRUE if at least one of the headers of the list belongs to
3527  * a message that has been fully retrieved.
3528  */
3529 #if 0 /* no longer in use. delete in 2007.10 */
3530 static gboolean
3531 has_retrieved_msgs (TnyList *list)
3532 {
3533         TnyIterator *iter;
3534         gboolean found = FALSE;
3535
3536         iter = tny_list_create_iterator (list);
3537         while (!tny_iterator_is_done (iter) && !found) {
3538                 TnyHeader *header;
3539                 TnyHeaderFlags flags = 0;
3540
3541                 header = TNY_HEADER (tny_iterator_get_current (iter));
3542                 if (header) {
3543                         flags = tny_header_get_flags (header);
3544                         if (flags & TNY_HEADER_FLAG_CACHED)
3545 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3546                                 found = TRUE;
3547
3548                         g_object_unref (header);
3549                 }
3550
3551                 if (!found)
3552                         tny_iterator_next (iter);
3553         }
3554         g_object_unref (iter);
3555
3556         return found;
3557 }
3558 #endif /* 0 */
3559
3560
3561 /*
3562  * Shows a confirmation dialog to the user when we're moving messages
3563  * from a remote server to the local storage. Returns the dialog
3564  * response. If it's other kind of movement the it always returns
3565  * GTK_RESPONSE_OK
3566  */
3567 gint
3568 msgs_move_to_confirmation (GtkWindow *win,
3569                            TnyFolder *dest_folder,
3570                            gboolean delete,
3571                            TnyList *headers)
3572 {
3573         gint response = GTK_RESPONSE_OK;
3574
3575         /* If the destination is a local folder (or MMC folder )*/
3576         if (!modest_tny_folder_is_remote_folder (dest_folder)) {
3577
3578                 gboolean is_online;
3579                 TnyDevice *device;
3580                 
3581                 TnyFolder *src_folder = NULL;
3582                 TnyIterator *iter = NULL;
3583                 TnyHeader *header = NULL;
3584
3585                 /* get the device */
3586                 
3587                 device = modest_runtime_get_device ();
3588                 if (device)
3589                         is_online = tny_device_is_online (device);
3590                 else {
3591                         g_warning ("failed to get tny device"); /* should not happend */
3592                         is_online = FALSE;
3593                 }
3594                                 
3595                 /* Get source folder */
3596                 iter = tny_list_create_iterator (headers);
3597                 header = TNY_HEADER (tny_iterator_get_current (iter));
3598                 if (header) {
3599                         src_folder = tny_header_get_folder (header);
3600                         g_object_unref (header);
3601                 }
3602
3603                 g_object_unref (iter);
3604
3605                 /* if no src_folder, message may be an attahcment */
3606                 if (src_folder == NULL) 
3607                         return GTK_RESPONSE_CANCEL;
3608
3609                 /* If the source is a remote folder */
3610                 if (!is_online && modest_tny_folder_is_remote_folder (src_folder)) {
3611
3612                         const gchar *message = NULL;
3613                         message = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs",
3614                                             tny_list_get_length (headers));
3615                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3616                                                                             (const gchar *) message);
3617                 } else
3618                         response = GTK_RESPONSE_OK;
3619                 
3620                 g_object_unref (src_folder);
3621         }
3622         
3623         return response;
3624 }
3625
3626
3627
3628 static void
3629 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3630 {
3631         ModestMsgViewWindow *self = NULL;
3632
3633         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3634         self = MODEST_MSG_VIEW_WINDOW (object);
3635         
3636         if (!modest_msg_view_window_select_next_message (self))
3637                 if (!modest_msg_view_window_select_previous_message (self))
3638                         /* No more messages to view, so close this window */
3639                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3640 }
3641
3642 void
3643 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3644                                              gpointer user_data)
3645 {
3646         GObject *win = modest_mail_operation_get_source (mail_op);
3647         const GError *error = NULL;
3648         const gchar *message = NULL;
3649         
3650         /* Get error message */
3651         error = modest_mail_operation_get_error (mail_op);
3652         if (error != NULL && error->message != NULL) {
3653                 message = error->message;
3654         } else {
3655                 message = _("mail_in_ui_folder_move_target_error");
3656         }
3657         
3658         /* Show notification dialog */
3659         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3660         g_object_unref (win);
3661 }
3662
3663 void
3664 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3665                                               gpointer user_data)
3666 {
3667         GObject *win = modest_mail_operation_get_source (mail_op);
3668         const GError *error = modest_mail_operation_get_error (mail_op);
3669
3670         g_return_if_fail (error != NULL);
3671         if (error->message != NULL)             
3672                 g_printerr ("modest: %s\n", error->message);
3673         else
3674                 g_printerr ("modest: unkonw error on send&receive operation");
3675
3676         /* Show error message */
3677 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3678 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3679 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3680 /*      else  */
3681 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3682 /*                                                      _CS("sfil_ib_unable_to_send")); */
3683         g_object_unref (win);
3684 }
3685
3686 static void
3687 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3688                        TnyHeader *header, 
3689                        TnyMsg *msg, 
3690                        gpointer user_data)
3691 {
3692         TnyList *parts;
3693         TnyIterator *iter;
3694         gint pending_purges = 0;
3695         gboolean some_purged = FALSE;
3696         ModestWindow *win = MODEST_WINDOW (user_data);
3697         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3698
3699         /* If there was any error */
3700         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3701                 modest_window_mgr_unregister_header (mgr, header);
3702                 return;
3703         }
3704
3705         /* Once the message has been retrieved for purging, we check if
3706          * it's all ok for purging */
3707
3708         parts = tny_simple_list_new ();
3709         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3710         iter = tny_list_create_iterator (parts);
3711
3712         while (!tny_iterator_is_done (iter)) {
3713                 TnyMimePart *part;
3714                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3715                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3716                         if (tny_mime_part_is_purged (part))
3717                                 some_purged = TRUE;
3718                         else
3719                                 pending_purges++;
3720                 }
3721
3722                 if (part)
3723                         g_object_unref (part);
3724
3725                 tny_iterator_next (iter);
3726         }
3727
3728         if (pending_purges>0) {
3729                 gint response;
3730                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3731
3732                 if (response == GTK_RESPONSE_OK) {
3733                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3734                         tny_iterator_first (iter);
3735                         while (!tny_iterator_is_done (iter)) {
3736                                 TnyMimePart *part;
3737                                 
3738                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3739                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3740                                         tny_mime_part_set_purged (part);
3741
3742                                 if (part)
3743                                         g_object_unref (part);
3744
3745                                 tny_iterator_next (iter);
3746                         }
3747                         
3748                         tny_msg_rewrite_cache (msg);
3749                 }
3750         } else {
3751                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3752         }
3753
3754         /* remove attachments */
3755         tny_iterator_first (iter);
3756         while (!tny_iterator_is_done (iter)) {
3757                 TnyMimePart *part;
3758                         
3759                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3760                 if (part) {
3761                         /* One for the reference given by tny_iterator_get_current(): */
3762                         g_object_unref (part);
3763
3764                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
3765                          * Otherwise, this seems useless. */
3766                 }
3767
3768                 tny_iterator_next (iter);
3769         }
3770         modest_window_mgr_unregister_header (mgr, header);
3771
3772         g_object_unref (iter);
3773         g_object_unref (parts);
3774 }
3775
3776 static void
3777 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3778                                                      ModestMainWindow *win)
3779 {
3780         GtkWidget *header_view;
3781         TnyList *header_list;
3782         TnyIterator *iter;
3783         TnyHeader *header;
3784         TnyHeaderFlags flags;
3785         ModestWindow *msg_view_window =  NULL;
3786         gboolean found;
3787
3788         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3789
3790         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3791                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3792
3793         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3794
3795         if (tny_list_get_length (header_list) == 1) {
3796                 iter = tny_list_create_iterator (header_list);
3797                 header = TNY_HEADER (tny_iterator_get_current (iter));
3798                 g_object_unref (iter);
3799         } else {
3800                 return;
3801         }
3802
3803         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3804                                                           header, &msg_view_window);
3805         flags = tny_header_get_flags (header);
3806         if (!(flags & TNY_HEADER_FLAG_CACHED))
3807                 return;
3808         if (found) {
3809                 if (msg_view_window != NULL) 
3810                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3811                 else {
3812                         /* do nothing; uid was registered before, so window is probably on it's way */
3813                         g_warning ("debug: header %p has already been registered", header);
3814                 }
3815         } else {
3816                 ModestMailOperation *mail_op = NULL;
3817                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3818                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3819                                                                          G_OBJECT (win),
3820                                                                          modest_ui_actions_get_msgs_full_error_handler,
3821                                                                          NULL);
3822                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3823                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3824                 
3825                 g_object_unref (mail_op);
3826         }
3827         if (header)
3828                 g_object_unref (header);
3829         if (header_list)
3830                 g_object_unref (header_list);
3831 }
3832
3833 /**
3834  * Utility function that transfer messages from both the main window
3835  * and the msg view window when using the "Move to" dialog
3836  */
3837 static void
3838 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3839                                               ModestWindow *win)
3840 {
3841         TnyList *headers = NULL;
3842         gint response = 0;
3843         TnyAccount *dst_account = NULL;
3844         const gchar *proto_str = NULL;
3845         gboolean dst_is_pop = FALSE;
3846
3847         if (!TNY_IS_FOLDER (dst_folder)) {
3848                 modest_platform_information_banner (GTK_WIDGET (win),
3849                                                     NULL,
3850                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3851                 return;
3852         }
3853
3854         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
3855         proto_str = tny_account_get_proto (dst_account);
3856
3857         /* tinymail will return NULL for local folders it seems */
3858         dst_is_pop = proto_str &&
3859                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
3860                  MODEST_PROTOCOL_STORE_POP);
3861
3862         g_object_unref (dst_account);
3863
3864         /* Get selected headers */
3865         headers = get_selected_headers (MODEST_WINDOW (win));
3866
3867         if (dst_is_pop) {
3868                 modest_platform_information_banner (GTK_WIDGET (win),
3869                                                     NULL,
3870                                                     ngettext("mail_in_ui_folder_move_target_error",
3871                                                              "mail_in_ui_folder_move_targets_error",
3872                                                              tny_list_get_length (headers)));
3873                 g_object_unref (headers);
3874                 return;
3875         }
3876
3877         /* Ask for user confirmation */
3878         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3879                                               TNY_FOLDER (dst_folder), 
3880                                               TRUE,
3881                                               headers);
3882
3883         /* Transfer messages */
3884         if (response == GTK_RESPONSE_OK) {
3885                 ModestMailOperation *mail_op = 
3886                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3887                                                                        G_OBJECT(win),
3888                                                                        modest_ui_actions_move_folder_error_handler,
3889                                                                        NULL);
3890                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3891                                                  mail_op);
3892
3893                 modest_mail_operation_xfer_msgs (mail_op, 
3894                                                  headers,
3895                                                  TNY_FOLDER (dst_folder),
3896                                                  TRUE,
3897                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3898                                                  NULL);
3899
3900                 g_object_unref (G_OBJECT (mail_op));
3901         }
3902         g_object_unref (headers);
3903 }
3904
3905 /*
3906  * UI handler for the "Move to" action when invoked from the
3907  * ModestMainWindow
3908  */
3909 static void 
3910 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3911                                           GtkWidget *folder_view,
3912                                           TnyFolderStore *dst_folder,
3913                                           ModestMainWindow *win)
3914 {
3915         GtkWidget *header_view = NULL;
3916         ModestMailOperation *mail_op = NULL;
3917         TnyFolderStore *src_folder;
3918
3919         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3920
3921         /* Get the source folder */
3922         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3923         
3924         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3925         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3926                                                                       src_folder))
3927                 goto end;
3928
3929         /* Get header view */
3930         header_view = 
3931                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3932
3933         /* Get folder or messages to transfer */
3934         if (gtk_widget_is_focus (folder_view)) {
3935                 GtkTreeSelection *sel;
3936
3937                 /* Allow only to transfer folders to the local root folder */
3938                 if (TNY_IS_ACCOUNT (dst_folder) && 
3939                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3940                         goto end;
3941                 
3942                 /* Clean folder on header view before moving it */
3943                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3944                 gtk_tree_selection_unselect_all (sel);
3945
3946                 if (TNY_IS_FOLDER (src_folder)) {
3947                         mail_op = 
3948                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3949                                                                                G_OBJECT(win),
3950                                                                                modest_ui_actions_move_folder_error_handler,
3951                                                                                NULL);
3952                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3953                                                          mail_op);
3954
3955                         modest_mail_operation_xfer_folder (mail_op, 
3956                                                            TNY_FOLDER (src_folder),
3957                                                            dst_folder,
3958                                                            TRUE, NULL, NULL);
3959                         /* Unref mail operation */
3960                         g_object_unref (G_OBJECT (mail_op));
3961                 } else {
3962                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3963                 }
3964         } else if (gtk_widget_is_focus (header_view)) {
3965                 /* Transfer messages */
3966                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3967         }
3968         
3969  end:
3970     if (src_folder)
3971         g_object_unref (src_folder);
3972 }
3973
3974
3975 /*
3976  * UI handler for the "Move to" action when invoked from the
3977  * ModestMsgViewWindow
3978  */
3979 static void 
3980 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3981                                               TnyFolderStore *dst_folder,
3982                                               ModestMsgViewWindow *win)
3983 {
3984         TnyHeader *header = NULL;
3985         TnyFolder *src_folder;
3986
3987         /* Create header list */
3988         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3989         src_folder = tny_header_get_folder(header);
3990         g_object_unref (header);
3991
3992         /* Transfer the message */
3993         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3994                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3995
3996         g_object_unref (src_folder);
3997 }
3998
3999 void 
4000 modest_ui_actions_on_move_to (GtkAction *action, 
4001                               ModestWindow *win)
4002 {
4003         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4004         gint result = 0;
4005         TnyFolderStore *dst_folder = NULL;
4006         ModestMainWindow *main_window;
4007
4008         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4009                           MODEST_IS_MSG_VIEW_WINDOW (win));
4010
4011         /* Get the main window if exists */
4012         if (MODEST_IS_MAIN_WINDOW (win))
4013                 main_window = MODEST_MAIN_WINDOW (win);
4014         else
4015                 main_window = 
4016                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4017
4018         /* Get the folder view widget if exists */
4019         if (main_window)
4020                 folder_view = modest_main_window_get_child_widget (main_window,
4021                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
4022         else
4023                 folder_view = NULL;
4024
4025         /* Create and run the dialog */
4026         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4027         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4028         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4029         result = gtk_dialog_run (GTK_DIALOG(dialog));
4030         g_object_ref (tree_view);
4031         gtk_widget_destroy (dialog);
4032
4033         if (result != GTK_RESPONSE_ACCEPT)
4034                 return;
4035
4036         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4037         /* Offer the connection dialog if necessary: */
4038         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
4039                                                                       dst_folder)) {
4040
4041                 /* Do window specific stuff */
4042                 if (MODEST_IS_MAIN_WINDOW (win))
4043                         modest_ui_actions_on_main_window_move_to (action,
4044                                                                   folder_view,
4045                                                                   dst_folder,
4046                                                                   MODEST_MAIN_WINDOW (win));
4047                 else
4048                         modest_ui_actions_on_msg_view_window_move_to (action,
4049                                                                       dst_folder,
4050                                                                       MODEST_MSG_VIEW_WINDOW (win));
4051         }
4052         if (dst_folder)
4053                 g_object_unref (dst_folder);
4054 }
4055
4056 /*
4057  * Calls #HeadersFunc for each header already selected in the main
4058  * window or the message currently being shown in the msg view window
4059  */
4060 static void
4061 do_headers_action (ModestWindow *win, 
4062                    HeadersFunc func,
4063                    gpointer user_data)
4064 {
4065         TnyList *headers_list = NULL;
4066         TnyIterator *iter = NULL;
4067         TnyHeader *header = NULL;
4068         TnyFolder *folder = NULL;
4069
4070         /* Get headers */
4071         headers_list = get_selected_headers (win);
4072         if (!headers_list)
4073                 return;
4074
4075         /* Get the folder */
4076         iter = tny_list_create_iterator (headers_list);
4077         header = TNY_HEADER (tny_iterator_get_current (iter));
4078         if (header) {
4079                 folder = tny_header_get_folder (header);
4080                 g_object_unref (header);
4081         }
4082
4083         /* Call the function for each header */
4084         while (!tny_iterator_is_done (iter)) {
4085                 header = TNY_HEADER (tny_iterator_get_current (iter));
4086                 func (header, win, user_data);
4087                 g_object_unref (header);
4088                 tny_iterator_next (iter);
4089         }
4090
4091         /* Trick: do a poke status in order to speed up the signaling
4092            of observers */
4093         tny_folder_poke_status (folder);
4094
4095         /* Frees */
4096         g_object_unref (folder);
4097         g_object_unref (iter);
4098         g_object_unref (headers_list);
4099 }
4100
4101 void 
4102 modest_ui_actions_view_attachment (GtkAction *action,
4103                                    ModestWindow *window)
4104 {
4105         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4106                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4107         } else {
4108                 /* not supported window for this action */
4109                 g_return_if_reached ();
4110         }
4111 }
4112
4113 void
4114 modest_ui_actions_save_attachments (GtkAction *action,
4115                                     ModestWindow *window)
4116 {
4117         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4118                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4119         } else {
4120                 /* not supported window for this action */
4121                 g_return_if_reached ();
4122         }
4123 }
4124
4125 void
4126 modest_ui_actions_remove_attachments (GtkAction *action,
4127                                       ModestWindow *window)
4128 {
4129         if (MODEST_IS_MAIN_WINDOW (window)) {
4130                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4131         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4132                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4133         } else {
4134                 /* not supported window for this action */
4135                 g_return_if_reached ();
4136         }
4137 }
4138
4139 void 
4140 modest_ui_actions_on_settings (GtkAction *action, 
4141                                ModestWindow *win)
4142 {
4143         GtkWidget *dialog;
4144
4145         dialog = modest_platform_get_global_settings_dialog ();
4146         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4147         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4148         gtk_widget_show_all (dialog);
4149
4150         gtk_dialog_run (GTK_DIALOG (dialog));
4151
4152         gtk_widget_destroy (dialog);
4153 }
4154
4155 void 
4156 modest_ui_actions_on_help (GtkAction *action, 
4157                            ModestWindow *win)
4158 {
4159         const gchar *help_id = NULL;
4160
4161         if (MODEST_IS_MAIN_WINDOW (win)) {
4162                 const gchar *action_name;
4163                 action_name = gtk_action_get_name (action);
4164
4165                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
4166                     !strcmp (action_name, "HeaderViewCSMHelp")) {
4167                         GtkWidget *folder_view;
4168                         TnyFolderStore *folder_store;
4169                         /* Get selected folder */
4170                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4171                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
4172                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4173
4174                         /* Switch help_id */
4175                         if (TNY_IS_FOLDER (folder_store)) {
4176                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4177                                 case TNY_FOLDER_TYPE_NORMAL:
4178                                         help_id = "applications_email_managefolders";
4179                                         break;
4180                                 case TNY_FOLDER_TYPE_INBOX:
4181                                         help_id = "applications_email_inbox";
4182                                         break;
4183                                 case TNY_FOLDER_TYPE_OUTBOX:
4184                                         help_id = "applications_email_outbox";
4185                                         break;
4186                                 case TNY_FOLDER_TYPE_SENT:
4187                                         help_id = "applications_email_sent";
4188                                         break;
4189                                 case TNY_FOLDER_TYPE_DRAFTS:
4190                                         help_id = "applications_email_drafts";
4191                                         break;
4192                                 case TNY_FOLDER_TYPE_ARCHIVE:
4193                                         help_id = "applications_email_managefolders";
4194                                         break;
4195                                 default:
4196                                         help_id = "applications_email_managefolders";
4197                                 }
4198                         } else {
4199                                 help_id = "applications_email_mainview";        
4200                         }
4201                         g_object_unref (folder_store);
4202                 } else {
4203                         help_id = "applications_email_mainview";        
4204                 }
4205         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4206                 help_id = "applications_email_viewer";
4207         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4208                 help_id = "applications_email_editor";
4209
4210         modest_platform_show_help (GTK_WINDOW (win), help_id);
4211 }
4212
4213 void 
4214 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4215                                             ModestWindow *window)
4216 {
4217         ModestMailOperation *mail_op;
4218         TnyList *headers;
4219
4220         /* Get headers */
4221         headers = get_selected_headers (window);
4222         if (!headers)
4223                 return;
4224
4225         /* Create mail operation */
4226         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4227                                                                  G_OBJECT (window),
4228                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4229                                                                  NULL);
4230         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4231         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4232
4233         /* Frees */
4234         g_object_unref (headers);
4235         g_object_unref (mail_op);
4236 }
4237
4238 void
4239 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4240                                           ModestWindow *window)
4241 {
4242         g_return_if_fail (MODEST_IS_WINDOW (window));
4243         
4244         /* Update dimmed */     
4245         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4246 }
4247
4248 void
4249 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4250                                           ModestWindow *window)
4251 {
4252         g_return_if_fail (MODEST_IS_WINDOW (window));
4253
4254         /* Update dimmed */     
4255         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4256 }
4257
4258 void
4259 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4260                                           ModestWindow *window)
4261 {
4262         g_return_if_fail (MODEST_IS_WINDOW (window));
4263
4264         /* Update dimmed */     
4265         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4266 }
4267
4268 void
4269 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4270                                           ModestWindow *window)
4271 {
4272         g_return_if_fail (MODEST_IS_WINDOW (window));
4273
4274         /* Update dimmed */     
4275         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4276 }
4277
4278 void
4279 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4280                                           ModestWindow *window)
4281 {
4282         g_return_if_fail (MODEST_IS_WINDOW (window));
4283
4284         /* Update dimmed */     
4285         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4286 }
4287
4288 void
4289 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4290                                                  ModestWindow *window)
4291 {
4292         g_return_if_fail (MODEST_IS_WINDOW (window));
4293
4294         /* Update dimmed */     
4295         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4296 }
4297
4298 void
4299 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4300                                                      ModestWindow *window)
4301 {
4302         g_return_if_fail (MODEST_IS_WINDOW (window));
4303
4304         /* Update dimmed */     
4305         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4306 }
4307
4308 void
4309 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4310                                                      ModestWindow *window)
4311 {
4312         g_return_if_fail (MODEST_IS_WINDOW (window));
4313
4314         /* Update dimmed */     
4315         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4316 }
4317
4318 void
4319 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4320 {
4321         g_return_if_fail (MODEST_IS_WINDOW (window));
4322
4323         /* Update dimmed */     
4324         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4325 }
4326
4327 void
4328 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4329 {
4330         g_return_if_fail (MODEST_IS_WINDOW (window));
4331
4332         modest_platform_show_search_messages (GTK_WINDOW (window));
4333 }
4334
4335 void     
4336 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4337 {
4338         g_return_if_fail (MODEST_IS_WINDOW (win));
4339         modest_platform_show_addressbook (GTK_WINDOW (win));
4340 }
4341
4342
4343 void
4344 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4345                                           ModestWindow *window)
4346 {
4347         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4348
4349         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4350 }
4351
4352 static void 
4353 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4354                                    ModestMailOperationState *state,
4355                                    gpointer user_data)
4356 {
4357         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4358
4359         /* Set send/receive operation finished */       
4360         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4361                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4362         
4363 }
4364
4365