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