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