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