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