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