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