* Fixes NB#63001, now we get errors if the SMTP connection fails
[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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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_MAIN_WINDOW_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         TnyAccount *store_account = NULL;
1575
1576         /* If no account name was provided then get the current account, and if
1577            there is no current account then pick the default one: */
1578         if (!account_name) {
1579                 acc_name = g_strdup (modest_window_get_active_account(win));
1580                 if (!acc_name)
1581                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1582                 if (!acc_name) {
1583                         g_printerr ("modest: cannot get default account\n");
1584                         return;
1585                 }
1586         } else {
1587                 acc_name = g_strdup (account_name);
1588         }
1589
1590
1591         /* Ensure that we have a connection available */
1592         store_account =
1593                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1594                                                              acc_name,
1595                                                              TNY_ACCOUNT_TYPE_STORE);
1596         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1597                 g_object_unref (store_account);
1598                 return;
1599         }
1600         g_object_unref (store_account);
1601
1602         /* Set send/receive operation in progress */    
1603         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1604
1605         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1606                                                                  G_OBJECT (win),
1607                                                                  modest_ui_actions_send_receive_error_handler,
1608                                                                  NULL);
1609
1610         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1611                           G_CALLBACK (_on_send_receive_progress_changed), 
1612                           win);
1613
1614         /* Send & receive. */
1615         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1616         /* Receive and then send. The operation is tagged initially as
1617            a receive operation because the account update performs a
1618            receive and then a send. The operation changes its type
1619            internally, so the progress objects will receive the proper
1620            progress information */
1621         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1622         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1623         g_object_unref (G_OBJECT (mail_op));
1624         
1625         /* Free */
1626         g_free (acc_name);
1627 }
1628
1629
1630 static void
1631 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1632                                   ModestWindow *win)
1633 {
1634         TnyTransportAccount *transport_account;
1635         TnySendQueue *send_queue = NULL;
1636         GError *error = NULL;
1637
1638         /* Get transport account */
1639         transport_account =
1640                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1641                                       (modest_runtime_get_account_store(),
1642                                        account_name,
1643                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1644         if (!transport_account) {
1645                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1646                 goto frees;
1647         }
1648
1649         /* Get send queue*/
1650         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1651         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1652                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1653                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1654                              "modest: could not find send queue for account\n");
1655         } else {
1656                 /* Keeep messages in outbox folder */
1657                 tny_send_queue_cancel (send_queue, FALSE, &error);
1658         }       
1659
1660  frees:
1661         if (transport_account != NULL) 
1662                 g_object_unref (G_OBJECT (transport_account));
1663 }
1664
1665 static void
1666 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1667 {
1668         GSList *account_names, *iter;
1669
1670         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1671                                                           TRUE);
1672
1673         iter = account_names;
1674         while (iter) {                  
1675                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1676                 iter = g_slist_next (iter);
1677         }
1678
1679         modest_account_mgr_free_account_names (account_names);
1680         account_names = NULL;
1681 }
1682
1683 void
1684 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1685
1686 {
1687         /* Check if accounts exist */
1688         gboolean accounts_exist = 
1689                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1690         
1691         /* If not, allow the user to create an account before trying to send/receive. */
1692         if (!accounts_exist)
1693                 modest_ui_actions_on_accounts (NULL, win);
1694         
1695         /* Cancel all sending operaitons */     
1696         modest_ui_actions_cancel_send_all (win);
1697 }
1698
1699 /*
1700  * Refreshes all accounts. This function will be used by automatic
1701  * updates
1702  */
1703 void
1704 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1705 {
1706         GSList *account_names, *iter;
1707
1708         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1709                                                           TRUE);
1710
1711         iter = account_names;
1712         while (iter) {                  
1713                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1714                 iter = g_slist_next (iter);
1715         }
1716
1717         modest_account_mgr_free_account_names (account_names);
1718         account_names = NULL;
1719 }
1720
1721 void 
1722 modest_do_refresh_current_folder(ModestWindow *win)
1723 {
1724         /* Refresh currently selected folder. Note that if we only
1725            want to retreive the headers, then the refresh only will
1726            invoke a poke_status over all folders, i.e., only the
1727            total/unread count will be updated */
1728         if (MODEST_IS_MAIN_WINDOW (win)) {
1729                 GtkWidget *header_view, *folder_view;
1730                 TnyFolderStore *folder_store;
1731
1732                 /* Get folder and header view */
1733                 folder_view = 
1734                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1735                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1736                 if (!folder_view)
1737                         return;
1738
1739                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1740
1741                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1742                         header_view = 
1743                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1744                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1745                 
1746                         /* We do not need to set the contents style
1747                            because it hasn't changed. We also do not
1748                            need to save the widget status. Just force
1749                            a refresh */
1750                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1751                                                        TNY_FOLDER (folder_store),
1752                                                        folder_refreshed_cb,
1753                                                        MODEST_MAIN_WINDOW (win));
1754                 }
1755                 
1756                 if (folder_store)
1757                         g_object_unref (folder_store);
1758         }
1759 }
1760
1761
1762 /*
1763  * Handler of the click on Send&Receive button in the main toolbar
1764  */
1765 void
1766 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1767 {
1768         /* Check if accounts exist */
1769         gboolean accounts_exist = 
1770                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1771         
1772         /* If not, allow the user to create an account before trying to send/receive. */
1773         if (!accounts_exist)
1774                 modest_ui_actions_on_accounts (NULL, win);
1775
1776         modest_do_refresh_current_folder (win);
1777         
1778         /* Refresh the active account */
1779         modest_ui_actions_do_send_receive (NULL, win);
1780 }
1781
1782
1783 void
1784 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1785 {
1786         ModestConf *conf;
1787         GtkWidget *header_view;
1788         
1789         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1790
1791         header_view = modest_main_window_get_child_widget (main_window,
1792                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1793         if (!header_view)
1794                 return;
1795
1796         conf = modest_runtime_get_conf ();
1797         
1798         /* what is saved/restored is depending on the style; thus; we save with
1799          * old style, then update the style, and restore for this new style
1800          */
1801         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1802         
1803         if (modest_header_view_get_style
1804             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1805                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1806                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1807         else
1808                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1809                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1810
1811         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1812                                       MODEST_CONF_HEADER_VIEW_KEY);
1813 }
1814
1815
1816 void 
1817 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1818                                       TnyHeader *header,
1819                                       ModestMainWindow *main_window)
1820 {
1821         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1822         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1823         
1824         /* in the case the folder is empty, show the empty folder message and focus
1825          * folder view */
1826         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1827                 if (modest_header_view_is_empty (header_view)) {
1828                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1829                         GtkWidget *folder_view = 
1830                                 modest_main_window_get_child_widget (main_window,
1831                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1832                         if (folder != NULL) 
1833                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1834                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1835                         return;
1836                 }
1837         }
1838         /* If no header has been selected then exit */
1839         if (!header)
1840                 return;
1841
1842         /* Update focus */
1843         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1844             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1845
1846         /* Update toolbar dimming state */
1847         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1848 }
1849
1850 void
1851 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1852                                        TnyHeader *header,
1853                                        ModestMainWindow *main_window)
1854 {
1855         TnyList *headers;
1856
1857         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1858         
1859         if (!header)
1860                 return;
1861
1862
1863 /*      headers = tny_simple_list_new (); */
1864 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1865         headers = modest_header_view_get_selected_headers (header_view);
1866
1867         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1868
1869         g_object_unref (headers);
1870 }
1871
1872 static void
1873 set_active_account_from_tny_account (TnyAccount *account,
1874                                      ModestWindow *window)
1875 {
1876         const gchar *server_acc_name = tny_account_get_id (account);
1877         
1878         /* We need the TnyAccount provided by the
1879            account store because that is the one that
1880            knows the name of the Modest account */
1881         TnyAccount *modest_server_account = modest_server_account = 
1882                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1883                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1884                                                              server_acc_name);
1885         if (!modest_server_account) {
1886                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1887                 return;
1888         }
1889
1890         /* Update active account, but only if it's not a pseudo-account */
1891         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1892             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1893                 const gchar *modest_acc_name = 
1894                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1895                 if (modest_acc_name)
1896                         modest_window_set_active_account (window, modest_acc_name);
1897         }
1898         
1899         g_object_unref (modest_server_account);
1900 }
1901
1902
1903 static void
1904 folder_refreshed_cb (ModestMailOperation *mail_op, 
1905                      TnyFolder *folder, 
1906                      gpointer user_data)
1907 {
1908         ModestMainWindow *win = NULL;
1909         GtkWidget *header_view;
1910         gboolean folder_empty = FALSE;
1911         gboolean all_marked_as_deleted = FALSE;
1912
1913         g_return_if_fail (TNY_IS_FOLDER (folder));
1914
1915         win = MODEST_MAIN_WINDOW (user_data);
1916         header_view = 
1917                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1918
1919         if (header_view) {
1920                 TnyFolder *current_folder;
1921
1922                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1923                 if (current_folder != NULL && folder != current_folder) {
1924                         g_object_unref (current_folder);
1925                         return;
1926                 }
1927                 g_object_unref (current_folder);
1928         }
1929
1930         /* Check if folder is empty and set headers view contents style */
1931         folder_empty = (tny_folder_get_all_count (folder) == 0);
1932         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1933         if (folder_empty || all_marked_as_deleted)
1934                 modest_main_window_set_contents_style (win,
1935                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1936 }
1937
1938 void 
1939 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1940                                                TnyFolderStore *folder_store, 
1941                                                gboolean selected,
1942                                                ModestMainWindow *main_window)
1943 {
1944         ModestConf *conf;
1945         GtkWidget *header_view;
1946
1947         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1948
1949         header_view = modest_main_window_get_child_widget(main_window,
1950                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1951         if (!header_view)
1952                 return;
1953         
1954         conf = modest_runtime_get_conf ();
1955
1956         if (TNY_IS_ACCOUNT (folder_store)) {
1957                 if (selected) {
1958                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1959                         
1960                         /* Show account details */
1961                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1962                 }
1963         } else {
1964                 if (TNY_IS_FOLDER (folder_store) && selected) {
1965                         
1966                         /* Update the active account */
1967                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1968                         if (account) {
1969                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1970                                 g_object_unref (account);
1971                                 account = NULL;
1972                         }
1973
1974                         /* Set the header style by default, it could
1975                            be changed later by the refresh callback to
1976                            empty */
1977                         modest_main_window_set_contents_style (main_window, 
1978                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1979
1980                         /* Set folder on header view. This function
1981                            will call tny_folder_refresh_async so we
1982                            pass a callback that will be called when
1983                            finished. We use that callback to set the
1984                            empty view if there are no messages */
1985                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1986                                                        TNY_FOLDER (folder_store),
1987                                                        folder_refreshed_cb,
1988                                                        main_window);
1989                         
1990                         /* Restore configuration. We need to do this
1991                            *after* the set_folder because the widget
1992                            memory asks the header view about its
1993                            folder  */
1994                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1995                                                       G_OBJECT(header_view),
1996                                                       MODEST_CONF_HEADER_VIEW_KEY);
1997                 } else {
1998                         /* Update the active account */
1999                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2000                         /* Save only if we're seeing headers */
2001                         if (modest_main_window_get_contents_style (main_window) ==
2002                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2003                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2004                                                            MODEST_CONF_HEADER_VIEW_KEY);
2005                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2006                 }
2007         }
2008
2009         /* Update toolbar dimming state */
2010         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2011 }
2012
2013 void 
2014 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2015                                      ModestWindow *win)
2016 {
2017         GtkWidget *dialog;
2018         gchar *txt, *item;
2019         gboolean online;
2020
2021         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2022         
2023         online = tny_device_is_online (modest_runtime_get_device());
2024
2025         if (online) {
2026                 /* already online -- the item is simply not there... */
2027                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2028                                                  GTK_DIALOG_MODAL,
2029                                                  GTK_MESSAGE_WARNING,
2030                                                  GTK_BUTTONS_NONE,
2031                                                  _("The %s you selected cannot be found"),
2032                                                  item);
2033                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2034                 gtk_dialog_run (GTK_DIALOG(dialog));
2035         } else {
2036                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2037                                                       GTK_WINDOW (win),
2038                                                       GTK_DIALOG_MODAL,
2039                                                       _("mcen_bd_dialog_cancel"),
2040                                                       GTK_RESPONSE_REJECT,
2041                                                       _("mcen_bd_dialog_ok"),
2042                                                       GTK_RESPONSE_ACCEPT,
2043                                                       NULL);
2044                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2045                                          "Do you want to get online?"), item);
2046                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2047                                     gtk_label_new (txt), FALSE, FALSE, 0);
2048                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2049                 g_free (txt);
2050
2051                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2052                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2053                         /* TODO: Comment about why is this commented out: */
2054                         /* modest_platform_connect_and_wait (); */
2055                 }
2056         }
2057         gtk_widget_destroy (dialog);
2058 }
2059
2060 void
2061 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2062                                      ModestWindow *win)
2063 {
2064         /* g_message ("%s %s", __FUNCTION__, link); */
2065 }       
2066
2067
2068 void
2069 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2070                                         ModestWindow *win)
2071 {
2072         modest_platform_activate_uri (link);
2073 }
2074
2075 void
2076 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2077                                           ModestWindow *win)
2078 {
2079         modest_platform_show_uri_popup (link);
2080 }
2081
2082 void
2083 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2084                                              ModestWindow *win)
2085 {
2086         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2087 }
2088
2089 void
2090 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2091                                           const gchar *address,
2092                                           ModestWindow *win)
2093 {
2094         /* g_message ("%s %s", __FUNCTION__, address); */
2095 }
2096
2097 void
2098 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2099 {
2100         TnyTransportAccount *transport_account;
2101         ModestMailOperation *mail_operation;
2102         MsgData *data;
2103         gchar *account_name, *from;
2104         ModestAccountMgr *account_mgr;
2105         gchar *info_text = NULL;
2106
2107         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2108         
2109         data = modest_msg_edit_window_get_msg_data (edit_window);
2110
2111         account_mgr = modest_runtime_get_account_mgr();
2112         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2113         if (!account_name) 
2114                 account_name = modest_account_mgr_get_default_account (account_mgr);
2115         if (!account_name) {
2116                 g_printerr ("modest: no account found\n");
2117                 modest_msg_edit_window_free_msg_data (edit_window, data);
2118                 return;
2119         }
2120
2121         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2122                 account_name = g_strdup (data->account_name);
2123         }
2124
2125         transport_account =
2126                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2127                                       (modest_runtime_get_account_store(),
2128                                        account_name,
2129                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2130         if (!transport_account) {
2131                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2132                 g_free (account_name);
2133                 modest_msg_edit_window_free_msg_data (edit_window, data);
2134                 return;
2135         }
2136         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2137
2138         /* Create the mail operation */         
2139         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2140         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2141
2142         modest_mail_operation_save_to_drafts (mail_operation,
2143                                               transport_account,
2144                                               data->draft_msg,
2145                                               edit_window,
2146                                               from,
2147                                               data->to, 
2148                                               data->cc, 
2149                                               data->bcc,
2150                                               data->subject, 
2151                                               data->plain_body, 
2152                                               data->html_body,
2153                                               data->attachments,
2154                                               data->priority_flags);
2155         /* Frees */
2156         g_free (from);
2157         g_free (account_name);
2158         g_object_unref (G_OBJECT (transport_account));
2159         g_object_unref (G_OBJECT (mail_operation));
2160
2161         modest_msg_edit_window_free_msg_data (edit_window, data);
2162
2163         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2164         modest_platform_information_banner (NULL, NULL, info_text);
2165         g_free (info_text);
2166 }
2167
2168 /* For instance, when clicking the Send toolbar button when editing a message: */
2169 void
2170 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2171 {
2172         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2173
2174         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2175                 return;
2176         
2177         /* Offer the connection dialog, if necessary: */        
2178         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2179                 return;
2180         
2181         /* FIXME: Code added just for testing. The final version will
2182            use the send queue provided by tinymail and some
2183            classifier */
2184         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2185         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2186         if (!account_name) 
2187                 account_name = modest_account_mgr_get_default_account (account_mgr);
2188                 
2189         if (!account_name) {
2190                 /* Run account setup wizard */
2191                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2192                 if (!created)
2193                         return;
2194         }
2195         
2196         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2197
2198         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2199                 account_name = g_strdup (data->account_name);
2200         }
2201         
2202         /* Get the currently-active transport account for this modest account: */
2203         TnyTransportAccount *transport_account =
2204                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2205                                       (modest_runtime_get_account_store(),
2206                                        account_name));
2207         if (!transport_account) {
2208                 /* Run account setup wizard */
2209                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2210                 if (!created)
2211                         return;
2212         }
2213         
2214         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2215
2216         /* Create the mail operation */
2217         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2218         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2219
2220         modest_mail_operation_send_new_mail (mail_operation,
2221                                              transport_account,
2222                                              data->draft_msg,
2223                                              from,
2224                                              data->to, 
2225                                              data->cc, 
2226                                              data->bcc,
2227                                              data->subject, 
2228                                              data->plain_body, 
2229                                              data->html_body,
2230                                              data->attachments,
2231                                              data->priority_flags);
2232                                              
2233         /* Free data: */
2234         g_free (from);
2235         g_free (account_name);
2236         g_object_unref (G_OBJECT (transport_account));
2237         g_object_unref (G_OBJECT (mail_operation));
2238
2239         modest_msg_edit_window_free_msg_data (edit_window, data);
2240         modest_msg_edit_window_set_sent (edit_window, TRUE);
2241
2242         /* Save settings and close the window: */
2243         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2244 }
2245
2246 void 
2247 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2248                                   ModestMsgEditWindow *window)
2249 {
2250         ModestMsgEditFormatState *format_state = NULL;
2251
2252         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2253         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2254
2255         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2256                 return;
2257
2258         format_state = modest_msg_edit_window_get_format_state (window);
2259         g_return_if_fail (format_state != NULL);
2260
2261         format_state->bold = gtk_toggle_action_get_active (action);
2262         modest_msg_edit_window_set_format_state (window, format_state);
2263         g_free (format_state);
2264         
2265 }
2266
2267 void 
2268 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2269                                      ModestMsgEditWindow *window)
2270 {
2271         ModestMsgEditFormatState *format_state = NULL;
2272
2273         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2274         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2275
2276         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2277                 return;
2278
2279         format_state = modest_msg_edit_window_get_format_state (window);
2280         g_return_if_fail (format_state != NULL);
2281
2282         format_state->italics = gtk_toggle_action_get_active (action);
2283         modest_msg_edit_window_set_format_state (window, format_state);
2284         g_free (format_state);
2285         
2286 }
2287
2288 void 
2289 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2290                                      ModestMsgEditWindow *window)
2291 {
2292         ModestMsgEditFormatState *format_state = NULL;
2293
2294         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2295         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2296
2297         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2298                 return;
2299
2300         format_state = modest_msg_edit_window_get_format_state (window);
2301         g_return_if_fail (format_state != NULL);
2302
2303         format_state->bullet = gtk_toggle_action_get_active (action);
2304         modest_msg_edit_window_set_format_state (window, format_state);
2305         g_free (format_state);
2306         
2307 }
2308
2309 void 
2310 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2311                                      GtkRadioAction *selected,
2312                                      ModestMsgEditWindow *window)
2313 {
2314         ModestMsgEditFormatState *format_state = NULL;
2315         GtkJustification value;
2316
2317         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2318
2319         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2320                 return;
2321
2322         value = gtk_radio_action_get_current_value (selected);
2323
2324         format_state = modest_msg_edit_window_get_format_state (window);
2325         g_return_if_fail (format_state != NULL);
2326
2327         format_state->justification = value;
2328         modest_msg_edit_window_set_format_state (window, format_state);
2329         g_free (format_state);
2330 }
2331
2332 void 
2333 modest_ui_actions_on_select_editor_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_color (window);
2343 }
2344
2345 void 
2346 modest_ui_actions_on_select_editor_background_color (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_select_background_color (window);
2356 }
2357
2358 void 
2359 modest_ui_actions_on_insert_image (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         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2366                 return;
2367
2368         modest_msg_edit_window_insert_image (window);
2369 }
2370
2371 void 
2372 modest_ui_actions_on_attach_file (GtkAction *action,
2373                                   ModestMsgEditWindow *window)
2374 {
2375         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2376         g_return_if_fail (GTK_IS_ACTION (action));
2377
2378         modest_msg_edit_window_offer_attach_file (window);
2379 }
2380
2381 void 
2382 modest_ui_actions_on_remove_attachments (GtkAction *action,
2383                                          ModestMsgEditWindow *window)
2384 {
2385         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2386         g_return_if_fail (GTK_IS_ACTION (action));
2387
2388         modest_msg_edit_window_remove_attachments (window, NULL);
2389 }
2390
2391 static void
2392 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2393                                             gpointer user_data)
2394 {
2395         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2396         const GError *error = modest_mail_operation_get_error (mail_op);
2397
2398         if(error)
2399         {
2400                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2401                                                     modest_mail_operation_get_error (mail_op)->message);
2402         }
2403 }
2404
2405 static void
2406 modest_ui_actions_create_folder(GtkWidget *parent_window,
2407                                 GtkWidget *folder_view)
2408 {
2409         TnyFolderStore *parent_folder;
2410
2411         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2412         
2413         if (parent_folder) {
2414                 gboolean finished = FALSE;
2415                 gint result;
2416                 gchar *folder_name = NULL, *suggested_name = NULL;
2417                 const gchar *proto_str = NULL;
2418                 TnyAccount *account;
2419
2420                 if (TNY_IS_ACCOUNT (parent_folder))
2421                         account = g_object_ref (parent_folder);
2422                 else
2423                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2424                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2425
2426                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2427                     MODEST_PROTOCOL_STORE_POP) {
2428                         finished = TRUE;
2429                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2430                 }
2431                 g_object_unref (account);
2432
2433                 /* Run the new folder dialog */
2434                 while (!finished) {
2435                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2436                                                                         parent_folder,
2437                                                                         suggested_name,
2438                                                                         &folder_name);
2439
2440                         g_free (suggested_name);
2441                         suggested_name = NULL;
2442
2443                         if (result == GTK_RESPONSE_REJECT) {
2444                                 finished = TRUE;
2445                         } else {
2446                                 ModestMailOperation *mail_op;
2447                                 TnyFolder *new_folder = NULL;
2448
2449                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2450                                                                                           G_OBJECT(parent_window),
2451                                                                                           modest_ui_actions_new_folder_error_handler,
2452                                                                                           parent_window);
2453
2454                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2455                                                                  mail_op);
2456                                 new_folder = modest_mail_operation_create_folder (mail_op,
2457                                                                                   parent_folder,
2458                                                                                   (const gchar *) folder_name);
2459                                 if (new_folder) {
2460                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2461                                                                           new_folder, TRUE);
2462
2463                                         g_object_unref (new_folder);
2464                                         finished = TRUE;
2465                                 }
2466                                 g_object_unref (mail_op);
2467                         }
2468
2469                         suggested_name = folder_name;
2470                         folder_name = NULL;
2471                 }
2472
2473                 g_object_unref (parent_folder);
2474         }
2475 }
2476
2477 void 
2478 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2479 {
2480         GtkWidget *folder_view;
2481         
2482         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2483
2484         folder_view = modest_main_window_get_child_widget (main_window,
2485                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2486         if (!folder_view)
2487                 return;
2488
2489         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2490 }
2491
2492 static void
2493 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2494                                                gpointer user_data)
2495 {
2496         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2497         const GError *error = NULL;
2498         const gchar *message = NULL;
2499         
2500         /* Get error message */
2501         error = modest_mail_operation_get_error (mail_op);
2502         if (!error)
2503                 g_return_if_reached ();
2504
2505         switch (error->code) {
2506         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2507                 message = _CS("ckdg_ib_folder_already_exists");
2508                 break;
2509         default:
2510                 g_return_if_reached ();
2511         }
2512
2513         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2514 }
2515
2516 void 
2517 modest_ui_actions_on_rename_folder (GtkAction *action,
2518                                      ModestMainWindow *main_window)
2519 {
2520         TnyFolderStore *folder;
2521         GtkWidget *folder_view;
2522         GtkWidget *header_view; 
2523
2524         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2525
2526         folder_view = modest_main_window_get_child_widget (main_window,
2527                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2528         if (!folder_view)
2529                 return;
2530
2531         header_view = modest_main_window_get_child_widget (main_window,
2532                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2533         
2534         if (!header_view)
2535                 return;
2536
2537         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2538
2539         if (!folder)
2540                 return;
2541
2542         if (TNY_IS_FOLDER (folder)) {
2543                 gchar *folder_name;
2544                 gint response;
2545                 const gchar *current_name;
2546                 TnyFolderStore *parent;
2547                 gboolean do_rename = TRUE;
2548
2549                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2550                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2551                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2552                                                                      parent, current_name, 
2553                                                                      &folder_name);
2554                 g_object_unref (parent);
2555
2556                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2557                         do_rename = FALSE;
2558                 } else if (modest_platform_is_network_folderstore(folder) &&
2559                            !tny_device_is_online (modest_runtime_get_device())) {
2560                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2561                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2562                         g_object_unref(account);
2563                 }
2564
2565                 if (do_rename) {
2566                         ModestMailOperation *mail_op;
2567                         GtkTreeSelection *sel = NULL;
2568
2569                         mail_op = 
2570                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2571                                                                                G_OBJECT(main_window),
2572                                                                                modest_ui_actions_rename_folder_error_handler,
2573                                                                                main_window);
2574
2575                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2576                                                          mail_op);
2577
2578                         /* Clear the headers view */
2579                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2580                         gtk_tree_selection_unselect_all (sel);
2581
2582                         /* Select *after* the changes */
2583                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2584                                                           TNY_FOLDER(folder), TRUE);
2585
2586                         /* Actually rename the folder */
2587                         modest_mail_operation_rename_folder (mail_op,
2588                                                              TNY_FOLDER (folder),
2589                                                              (const gchar *) folder_name);
2590
2591                         g_object_unref (mail_op);
2592                         g_free (folder_name);
2593                 }
2594         }
2595         g_object_unref (folder);
2596 }
2597
2598 static void
2599 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2600                                                gpointer user_data)
2601 {
2602         GObject *win = modest_mail_operation_get_source (mail_op);
2603
2604         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2605                                                 _("mail_in_ui_folder_delete_error"));
2606         g_object_unref (win);
2607 }
2608
2609 static void
2610 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2611 {
2612         TnyFolderStore *folder;
2613         GtkWidget *folder_view;
2614         gint response;
2615         gchar *message;
2616         gboolean do_delete = TRUE;
2617
2618         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2619
2620         folder_view = modest_main_window_get_child_widget (main_window,
2621                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2622         if (!folder_view)
2623                 return;
2624
2625         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2626
2627         /* Show an error if it's an account */
2628         if (!TNY_IS_FOLDER (folder)) {
2629                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2630                                                         _("mail_in_ui_folder_delete_error"));
2631                 g_object_unref (G_OBJECT (folder));
2632                 return ;
2633         }
2634
2635         /* Ask the user */      
2636         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2637                                     tny_folder_get_name (TNY_FOLDER (folder)));
2638         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2639                                                             (const gchar *) message);
2640         g_free (message);
2641
2642         if (response != GTK_RESPONSE_OK) {
2643                 do_delete = FALSE;
2644         } else if (modest_platform_is_network_folderstore(folder) &&
2645                    !tny_device_is_online (modest_runtime_get_device())) {
2646                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2647                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2648                 g_object_unref(account);
2649         }
2650
2651         if (do_delete) {
2652                 ModestMailOperation *mail_op;
2653                 GtkTreeSelection *sel;
2654
2655                 /* Unselect the folder before deleting it to free the headers */
2656                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2657                 gtk_tree_selection_unselect_all (sel);
2658
2659                 /* Create the mail operation */
2660                 mail_op =
2661                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2662                                                                        G_OBJECT(main_window),
2663                                                                        modest_ui_actions_delete_folder_error_handler,
2664                                                                        NULL);
2665
2666                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2667                                                  mail_op);
2668                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2669                 g_object_unref (G_OBJECT (mail_op));
2670         }
2671
2672         g_object_unref (G_OBJECT (folder));
2673 }
2674
2675 void 
2676 modest_ui_actions_on_delete_folder (GtkAction *action,
2677                                      ModestMainWindow *main_window)
2678 {
2679         GtkWidget *folder_view;
2680         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2681
2682         delete_folder (main_window, FALSE);
2683         folder_view = modest_main_window_get_child_widget (main_window,
2684                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2685         if (!folder_view)
2686                 return;
2687         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2688 }
2689
2690 void 
2691 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2692 {
2693         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2694         
2695         delete_folder (main_window, TRUE);
2696 }
2697
2698
2699 static void
2700 show_error (GtkWidget *parent_widget, const gchar* text)
2701 {
2702         hildon_banner_show_information(parent_widget, NULL, text);
2703         
2704 #if 0
2705         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2706         /*
2707           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2708           (GtkDialogFlags)0,
2709           GTK_MESSAGE_ERROR,
2710           GTK_BUTTONS_OK,
2711           text ));
2712         */
2713                  
2714         gtk_dialog_run (dialog);
2715         gtk_widget_destroy (GTK_WIDGET (dialog));
2716 #endif
2717 }
2718
2719 void
2720 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2721                                          const gchar* server_account_name,
2722                                          gchar **username,
2723                                          gchar **password, 
2724                                          gboolean *cancel, 
2725                                          gboolean *remember,
2726                                          ModestMainWindow *main_window)
2727 {
2728         g_return_if_fail(server_account_name);
2729         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2730         
2731         /* Initalize output parameters: */
2732         if (cancel)
2733                 *cancel = FALSE;
2734                 
2735         if (remember)
2736                 *remember = TRUE;
2737                 
2738 #ifdef MODEST_PLATFORM_MAEMO
2739         /* Maemo uses a different (awkward) button order,
2740          * It should probably just use gtk_alternative_dialog_button_order ().
2741          */
2742         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2743                                               NULL,
2744                                               GTK_DIALOG_MODAL,
2745                                               _("mcen_bd_dialog_ok"),
2746                                               GTK_RESPONSE_ACCEPT,
2747                                               _("mcen_bd_dialog_cancel"),
2748                                               GTK_RESPONSE_REJECT,
2749                                               NULL);
2750 #else
2751         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2752                                               NULL,
2753                                               GTK_DIALOG_MODAL,
2754                                               GTK_STOCK_CANCEL,
2755                                               GTK_RESPONSE_REJECT,
2756                                               GTK_STOCK_OK,
2757                                               GTK_RESPONSE_ACCEPT,
2758                                               NULL);
2759 #endif /* MODEST_PLATFORM_MAEMO */
2760
2761         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2762         
2763         gchar *server_name = modest_server_account_get_hostname (
2764                 modest_runtime_get_account_mgr(), server_account_name);
2765         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2766                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2767                 *cancel = TRUE;
2768                 return;
2769         }
2770         
2771         /* This causes a warning because the logical ID has no %s in it, 
2772          * though the translation does, but there is not much we can do about that: */
2773         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2774         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2775                             FALSE, FALSE, 0);
2776         g_free (txt);
2777         g_free (server_name);
2778         server_name = NULL;
2779
2780         /* username: */
2781         gchar *initial_username = modest_server_account_get_username (
2782                 modest_runtime_get_account_mgr(), server_account_name);
2783         
2784         GtkWidget *entry_username = gtk_entry_new ();
2785         if (initial_username)
2786                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2787         /* Dim this if a connection has ever succeeded with this username,
2788          * as per the UI spec: */
2789         const gboolean username_known = 
2790                 modest_server_account_get_username_has_succeeded(
2791                         modest_runtime_get_account_mgr(), server_account_name);
2792         gtk_widget_set_sensitive (entry_username, !username_known);
2793         
2794 #ifdef MODEST_PLATFORM_MAEMO
2795         /* Auto-capitalization is the default, so let's turn it off: */
2796         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2797         
2798         /* Create a size group to be used by all captions.
2799          * Note that HildonCaption does not create a default size group if we do not specify one.
2800          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2801         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2802         
2803         GtkWidget *caption = hildon_caption_new (sizegroup, 
2804                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2805         gtk_widget_show (entry_username);
2806         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2807                 FALSE, FALSE, MODEST_MARGIN_HALF);
2808         gtk_widget_show (caption);
2809 #else 
2810         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2811                             TRUE, FALSE, 0);
2812 #endif /* MODEST_PLATFORM_MAEMO */      
2813                             
2814         /* password: */
2815         GtkWidget *entry_password = gtk_entry_new ();
2816         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2817         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2818         
2819 #ifdef MODEST_PLATFORM_MAEMO
2820         /* Auto-capitalization is the default, so let's turn it off: */
2821         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2822                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2823         
2824         caption = hildon_caption_new (sizegroup, 
2825                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2826         gtk_widget_show (entry_password);
2827         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2828                 FALSE, FALSE, MODEST_MARGIN_HALF);
2829         gtk_widget_show (caption);
2830         g_object_unref (sizegroup);
2831 #else 
2832         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2833                             TRUE, FALSE, 0);
2834 #endif /* MODEST_PLATFORM_MAEMO */      
2835                                 
2836 /* This is not in the Maemo UI spec:
2837         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2838         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2839                             TRUE, FALSE, 0);
2840 */
2841
2842         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2843         
2844         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2845                 if (username) {
2846                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2847                         
2848                         modest_server_account_set_username (
2849                                  modest_runtime_get_account_mgr(), server_account_name, 
2850                                  *username);
2851                                  
2852                         const gboolean username_was_changed = 
2853                                 (strcmp (*username, initial_username) != 0);
2854                         if (username_was_changed) {
2855                                 g_warning ("%s: tinymail does not yet support changing the "
2856                                         "username in the get_password() callback.\n", __FUNCTION__);
2857                         }
2858                 }
2859                         
2860                 if (password) {
2861                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2862                         
2863                         /* We do not save the password in the configuration, 
2864                          * because this function is only called for passwords that should 
2865                          * not be remembered:
2866                         modest_server_account_set_password (
2867                                  modest_runtime_get_account_mgr(), server_account_name, 
2868                                  *password);
2869                         */
2870                 }
2871                 
2872                 if (cancel)
2873                         *cancel   = FALSE;
2874                         
2875         } else {
2876                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2877                 
2878                 if (username)
2879                         *username = NULL;
2880                         
2881                 if (password)
2882                         *password = NULL;
2883                         
2884                 if (cancel)
2885                         *cancel   = TRUE;
2886         }
2887
2888 /* This is not in the Maemo UI spec:
2889         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2890                 *remember = TRUE;
2891         else
2892                 *remember = FALSE;
2893 */
2894
2895         gtk_widget_destroy (dialog);
2896         
2897         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2898 }
2899
2900 void
2901 modest_ui_actions_on_cut (GtkAction *action,
2902                           ModestWindow *window)
2903 {
2904         GtkWidget *focused_widget;
2905         GtkClipboard *clipboard;
2906
2907         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2908         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2909         if (GTK_IS_EDITABLE (focused_widget)) {
2910                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2911                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2912                 gtk_clipboard_store (clipboard);
2913         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2914                 GtkTextBuffer *buffer;
2915
2916                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2917                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2918                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2919                 gtk_clipboard_store (clipboard);
2920         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2921                 TnyList *header_list = modest_header_view_get_selected_headers (
2922                                 MODEST_HEADER_VIEW (focused_widget));
2923                 gboolean continue_download = FALSE;
2924                 gint num_of_unc_msgs;
2925
2926                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2927
2928                 if (num_of_unc_msgs)
2929                         continue_download = connect_to_get_msg(
2930                                                                 GTK_WINDOW (window),
2931                                                                 num_of_unc_msgs);
2932
2933                 if (num_of_unc_msgs == 0 || continue_download) {
2934 /*                      modest_platform_information_banner (
2935                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2936                         modest_header_view_cut_selection (
2937                                         MODEST_HEADER_VIEW (focused_widget));
2938                 }
2939
2940                 g_object_unref (header_list);
2941         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2942                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2943         }
2944 }
2945
2946 void
2947 modest_ui_actions_on_copy (GtkAction *action,
2948                            ModestWindow *window)
2949 {
2950         GtkClipboard *clipboard;
2951         GtkWidget *focused_widget;
2952         gboolean copied = TRUE;
2953
2954         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2955         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2956
2957         if (GTK_IS_LABEL (focused_widget)) {
2958                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2959                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2960                 gtk_clipboard_store (clipboard);
2961         } else if (GTK_IS_EDITABLE (focused_widget)) {
2962                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2963                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2964                 gtk_clipboard_store (clipboard);
2965         } else if (GTK_IS_HTML (focused_widget)) {
2966                 gtk_html_copy (GTK_HTML (focused_widget));
2967                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2968                 gtk_clipboard_store (clipboard);
2969         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2970                 GtkTextBuffer *buffer;
2971                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2972                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2973                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2974                 gtk_clipboard_store (clipboard);
2975         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2976                 TnyList *header_list = modest_header_view_get_selected_headers (
2977                                 MODEST_HEADER_VIEW (focused_widget));
2978                 gboolean continue_download = FALSE;
2979                 gint num_of_unc_msgs;
2980
2981                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2982
2983                 if (num_of_unc_msgs)
2984                         continue_download = connect_to_get_msg(
2985                                                                 GTK_WINDOW (window),
2986                                                                 num_of_unc_msgs);
2987
2988                 if (num_of_unc_msgs == 0 || continue_download) {
2989                         modest_platform_information_banner (
2990                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2991                         modest_header_view_copy_selection (
2992                                         MODEST_HEADER_VIEW (focused_widget));
2993                 } else
2994                         copied = FALSE;
2995
2996                 g_object_unref (header_list);
2997
2998         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2999                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3000         }
3001
3002         /* Show information banner if there was a copy to clipboard */
3003         if(copied)
3004                 modest_platform_information_banner (
3005                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3006 }
3007
3008 void
3009 modest_ui_actions_on_undo (GtkAction *action,
3010                            ModestWindow *window)
3011 {
3012         ModestEmailClipboard *clipboard = NULL;
3013
3014         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3015                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3016         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3017                 /* Clear clipboard source */
3018                 clipboard = modest_runtime_get_email_clipboard ();
3019                 modest_email_clipboard_clear (clipboard);               
3020         }
3021         else {
3022                 g_return_if_reached ();
3023         }
3024 }
3025
3026 void
3027 modest_ui_actions_on_redo (GtkAction *action,
3028                            ModestWindow *window)
3029 {
3030         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3031                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3032         }
3033         else {
3034                 g_return_if_reached ();
3035         }
3036 }
3037
3038
3039 static void
3040 paste_msgs_cb (const GObject *object, gpointer user_data)
3041 {
3042         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
3043         g_return_if_fail (GTK_IS_WIDGET (user_data));
3044         
3045         /* destroy information note */
3046         gtk_widget_destroy (GTK_WIDGET(user_data));
3047 }
3048
3049
3050 static void
3051 paste_as_attachment_free (gpointer data)
3052 {
3053         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3054
3055         gtk_widget_destroy (helper->banner);
3056         g_object_unref (helper->banner);
3057         g_free (helper);
3058 }
3059
3060 static void
3061 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3062                             TnyHeader *header,
3063                             TnyMsg *msg,
3064                             gpointer userdata)
3065 {
3066         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3067         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3068
3069         if (msg == NULL)
3070                 return;
3071
3072         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3073         
3074 }
3075
3076 void
3077 modest_ui_actions_on_paste (GtkAction *action,
3078                             ModestWindow *window)
3079 {
3080         GtkWidget *focused_widget = NULL;
3081         GtkWidget *inf_note = NULL;
3082         ModestMailOperation *mail_op = NULL;
3083
3084         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3085         if (GTK_IS_EDITABLE (focused_widget)) {
3086                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3087         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3088                 ModestEmailClipboard *e_clipboard = NULL;
3089                 e_clipboard = modest_runtime_get_email_clipboard ();
3090                 if (modest_email_clipboard_cleared (e_clipboard)) {
3091                         GtkTextBuffer *buffer;
3092                         GtkClipboard *clipboard;
3093
3094                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3095                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3096                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3097                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3098                         ModestMailOperation *mail_op;
3099                         TnyFolder *src_folder;
3100                         TnyList *data;
3101                         gboolean delete;
3102                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3103                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3104                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3105                                                                            _CS("ckct_nw_pasting"));
3106                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3107                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3108                                                              G_OBJECT (window));
3109                         if (helper->banner != NULL) {
3110                                 g_object_ref (G_OBJECT (helper->banner));
3111                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3112                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3113                         }
3114
3115                         if (data != NULL) {
3116                                 modest_mail_operation_get_msgs_full (mail_op, 
3117                                                                      data,
3118                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3119                                                                      helper,
3120                                                                      paste_as_attachment_free);
3121                         }
3122                 }
3123         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3124                 ModestEmailClipboard *clipboard = NULL;
3125                 TnyFolder *src_folder = NULL;
3126                 TnyFolderStore *folder_store = NULL;
3127                 TnyList *data = NULL;           
3128                 gboolean delete = FALSE;
3129                 
3130                 /* Check clipboard source */
3131                 clipboard = modest_runtime_get_email_clipboard ();
3132                 if (modest_email_clipboard_cleared (clipboard)) 
3133                         return;
3134                 
3135                 /* Get elements to paste */
3136                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3137
3138                 /* Create a new mail operation */
3139                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3140                 
3141                 /* Get destination folder */
3142                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3143
3144                 /* transfer messages  */
3145                 if (data != NULL) {
3146                         gint response = 0;
3147
3148                         /* Ask for user confirmation */
3149                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3150                                                               TNY_FOLDER (folder_store), 
3151                                                               delete,
3152                                                               data);
3153                         
3154                         if (response == GTK_RESPONSE_OK) {
3155                                 /* Launch notification */
3156                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3157                                                                              _CS("ckct_nw_pasting"));
3158                                 if (inf_note != NULL)  {
3159                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3160                                         gtk_widget_show (GTK_WIDGET(inf_note));
3161                                 }
3162
3163                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3164                                 modest_mail_operation_xfer_msgs (mail_op, 
3165                                                                  data,
3166                                                                  TNY_FOLDER (folder_store),
3167                                                                  delete,
3168                                                                  paste_msgs_cb,
3169                                                                  inf_note);                             
3170                         } else {
3171                                 g_object_unref (mail_op);
3172                         }
3173                         
3174                 } else if (src_folder != NULL) {                        
3175                         /* Launch notification */
3176                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3177                                                                      _CS("ckct_nw_pasting"));
3178                         if (inf_note != NULL)  {
3179                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3180                                 gtk_widget_show (GTK_WIDGET(inf_note));
3181                         }
3182                         
3183                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3184                         modest_mail_operation_xfer_folder (mail_op, 
3185                                                            src_folder,
3186                                                            folder_store,
3187                                                            delete,
3188                                                            paste_msgs_cb,
3189                                                            inf_note);
3190                 }
3191
3192                 /* Free */
3193                 if (data != NULL) 
3194                         g_object_unref (data);
3195                 if (src_folder != NULL) 
3196                         g_object_unref (src_folder);
3197                 if (folder_store != NULL) 
3198                         g_object_unref (folder_store);
3199         }
3200 }
3201
3202
3203 void
3204 modest_ui_actions_on_select_all (GtkAction *action,
3205                                  ModestWindow *window)
3206 {
3207         GtkWidget *focused_widget;
3208
3209         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3210         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3211                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3212         } else if (GTK_IS_LABEL (focused_widget)) {
3213                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3214         } else if (GTK_IS_EDITABLE (focused_widget)) {
3215                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3216         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3217                 GtkTextBuffer *buffer;
3218                 GtkTextIter start, end;
3219
3220                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3221                 gtk_text_buffer_get_start_iter (buffer, &start);
3222                 gtk_text_buffer_get_end_iter (buffer, &end);
3223                 gtk_text_buffer_select_range (buffer, &start, &end);
3224         } else if (GTK_IS_HTML (focused_widget)) {
3225                 gtk_html_select_all (GTK_HTML (focused_widget));
3226         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3227                 GtkWidget *header_view = focused_widget;
3228                 GtkTreeSelection *selection = NULL;
3229                 
3230                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3231                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3232                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3233                 }
3234                                 
3235                 /* Disable window dimming management */
3236                 modest_window_disable_dimming (MODEST_WINDOW(window));
3237                 
3238                 /* Select all messages */
3239                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3240                 gtk_tree_selection_select_all (selection);
3241
3242                 /* Set focuse on header view */
3243                 gtk_widget_grab_focus (header_view);
3244
3245
3246                 /* Enable window dimming management */
3247                 modest_window_enable_dimming (MODEST_WINDOW(window));
3248                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3249         }
3250
3251 }
3252
3253 void
3254 modest_ui_actions_on_mark_as_read (GtkAction *action,
3255                                    ModestWindow *window)
3256 {       
3257         g_return_if_fail (MODEST_IS_WINDOW(window));
3258                 
3259         /* Mark each header as read */
3260         do_headers_action (window, headers_action_mark_as_read, NULL);
3261 }
3262
3263 void
3264 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3265                                      ModestWindow *window)
3266 {       
3267         g_return_if_fail (MODEST_IS_WINDOW(window));
3268                 
3269         /* Mark each header as read */
3270         do_headers_action (window, headers_action_mark_as_unread, NULL);
3271 }
3272
3273 void
3274 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3275                                   GtkRadioAction *selected,
3276                                   ModestWindow *window)
3277 {
3278         gint value;
3279
3280         value = gtk_radio_action_get_current_value (selected);
3281         if (MODEST_IS_WINDOW (window)) {
3282                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3283         }
3284 }
3285
3286 void     
3287 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3288                                                GtkRadioAction *selected,
3289                                                ModestWindow *window)
3290 {
3291         TnyHeaderFlags flags;
3292         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293
3294         flags = gtk_radio_action_get_current_value (selected);
3295         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3296 }
3297
3298 void     
3299 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3300                                                   GtkRadioAction *selected,
3301                                                   ModestWindow *window)
3302 {
3303         gint file_format;
3304
3305         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3306
3307         file_format = gtk_radio_action_get_current_value (selected);
3308         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3309 }
3310
3311
3312 void     
3313 modest_ui_actions_on_zoom_plus (GtkAction *action,
3314                                 ModestWindow *window)
3315 {
3316         g_return_if_fail (MODEST_IS_WINDOW (window));
3317
3318         modest_window_zoom_plus (MODEST_WINDOW (window));
3319 }
3320
3321 void     
3322 modest_ui_actions_on_zoom_minus (GtkAction *action,
3323                                  ModestWindow *window)
3324 {
3325         g_return_if_fail (MODEST_IS_WINDOW (window));
3326
3327         modest_window_zoom_minus (MODEST_WINDOW (window));
3328 }
3329
3330 void     
3331 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3332                                            ModestWindow *window)
3333 {
3334         ModestWindowMgr *mgr;
3335         gboolean fullscreen, active;
3336         g_return_if_fail (MODEST_IS_WINDOW (window));
3337
3338         mgr = modest_runtime_get_window_mgr ();
3339
3340         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3341         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3342
3343         if (active != fullscreen) {
3344                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3345                 gtk_window_present (GTK_WINDOW (window));
3346         }
3347 }
3348
3349 void
3350 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3351                                         ModestWindow *window)
3352 {
3353         ModestWindowMgr *mgr;
3354         gboolean fullscreen;
3355
3356         g_return_if_fail (MODEST_IS_WINDOW (window));
3357
3358         mgr = modest_runtime_get_window_mgr ();
3359         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3360         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3361
3362         gtk_window_present (GTK_WINDOW (window));
3363 }
3364
3365 /* 
3366  * Used by modest_ui_actions_on_details to call do_headers_action 
3367  */
3368 static void
3369 headers_action_show_details (TnyHeader *header, 
3370                              ModestWindow *window,
3371                              gpointer user_data)
3372
3373 {
3374         GtkWidget *dialog;
3375         
3376         /* Create dialog */
3377         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3378
3379         /* Run dialog */
3380         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3381         gtk_widget_show_all (dialog);
3382         gtk_dialog_run (GTK_DIALOG (dialog));
3383
3384         gtk_widget_destroy (dialog);
3385 }
3386
3387 /*
3388  * Show the folder details in a ModestDetailsDialog widget
3389  */
3390 static void
3391 show_folder_details (TnyFolder *folder, 
3392                      GtkWindow *window)
3393 {
3394         GtkWidget *dialog;
3395         
3396         /* Create dialog */
3397         dialog = modest_details_dialog_new_with_folder (window, folder);
3398
3399         /* Run dialog */
3400         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3401         gtk_widget_show_all (dialog);
3402         gtk_dialog_run (GTK_DIALOG (dialog));
3403
3404         gtk_widget_destroy (dialog);
3405 }
3406
3407 /*
3408  * Show the header details in a ModestDetailsDialog widget
3409  */
3410 void     
3411 modest_ui_actions_on_details (GtkAction *action, 
3412                               ModestWindow *win)
3413 {
3414         TnyList * headers_list;
3415         TnyIterator *iter;
3416         TnyHeader *header;              
3417
3418         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3419                 TnyMsg *msg;
3420
3421                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3422                 if (!msg)
3423                         return;
3424                 g_object_unref (msg);           
3425
3426                 headers_list = get_selected_headers (win);
3427                 if (!headers_list)
3428                         return;
3429
3430                 iter = tny_list_create_iterator (headers_list);
3431
3432                 header = TNY_HEADER (tny_iterator_get_current (iter));
3433                 if (header) {
3434                         headers_action_show_details (header, win, NULL);
3435                         g_object_unref (header);
3436                 }
3437
3438                 g_object_unref (iter);
3439                 g_object_unref (headers_list);
3440
3441         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3442                 GtkWidget *folder_view, *header_view;
3443
3444                 /* Check which widget has the focus */
3445                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3446                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3447                 if (gtk_widget_is_focus (folder_view)) {
3448                         TnyFolderStore *folder_store
3449                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3450                         if (!folder_store) {
3451                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3452                                 return; 
3453                         }
3454                         /* Show only when it's a folder */
3455                         /* This function should not be called for account items, 
3456                          * because we dim the menu item for them. */
3457                         if (TNY_IS_FOLDER (folder_store)) {
3458                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3459                         }
3460
3461                         g_object_unref (folder_store);
3462
3463                 } else {
3464                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3465                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3466                         /* Show details of each header */
3467                         do_headers_action (win, headers_action_show_details, header_view);
3468                 }
3469         }
3470 }
3471
3472 void     
3473 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3474                                      ModestMsgEditWindow *window)
3475 {
3476         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3477
3478         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3479 }
3480
3481 void     
3482 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3483                                       ModestMsgEditWindow *window)
3484 {
3485         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3486
3487         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3488 }
3489
3490 void
3491 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3492                                        ModestMainWindow *main_window)
3493 {
3494         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3495
3496         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3497                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3498         else
3499                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3500 }
3501
3502 void 
3503 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3504                                      ModestWindow *window)
3505 {
3506         gboolean active, fullscreen = FALSE;
3507         ModestWindowMgr *mgr;
3508
3509         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3510
3511         /* Check if we want to toggle the toolbar vuew in fullscreen
3512            or normal mode */
3513         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3514                      "ViewShowToolbarFullScreen")) {
3515                 fullscreen = TRUE;
3516         }
3517
3518         /* Toggle toolbar */
3519         mgr = modest_runtime_get_window_mgr ();
3520         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3521 }
3522
3523 void     
3524 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3525                                            ModestMsgEditWindow *window)
3526 {
3527         modest_msg_edit_window_select_font (window);
3528 }
3529
3530 void
3531 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3532                                                   const gchar *display_name,
3533                                                   GtkWindow *window)
3534 {
3535         /* Do not change the application name if the widget has not
3536            the focus. This callback could be called even if the folder
3537            view has not the focus, because the handled signal could be
3538            emitted when the folder view is redrawn */
3539         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3540                 if (display_name)
3541                         gtk_window_set_title (window, display_name);
3542                 else
3543                         gtk_window_set_title (window, " ");
3544         }
3545 }
3546
3547 void
3548 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3549 {
3550         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3551         modest_msg_edit_window_select_contacts (window);
3552 }
3553
3554 void
3555 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3556 {
3557         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3558         modest_msg_edit_window_check_names (window, FALSE);
3559 }
3560
3561 static void
3562 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3563 {
3564         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3565                                          GTK_WIDGET (user_data));
3566 }
3567
3568 /*
3569  * This function is used to track changes in the selection of the
3570  * folder view that is inside the "move to" dialog to enable/disable
3571  * the OK button because we do not want the user to select a disallowed
3572  * destination for a folder.
3573  * The user also not desired to be able to use NEW button on items where
3574  * folder creation is not possibel.
3575  */
3576 static void
3577 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3578                                             TnyFolderStore *folder_store,
3579                                             gboolean selected,
3580                                             gpointer user_data)
3581 {
3582         GtkWidget *dialog = NULL;
3583         GtkWidget *ok_button = NULL, *new_button = NULL;
3584         GList *children = NULL;
3585         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3586         gboolean moving_folder = FALSE;
3587         gboolean is_local_account = TRUE;
3588         GtkWidget *folder_view = NULL;
3589         ModestTnyFolderRules rules;
3590
3591         if (!selected)
3592                 return;
3593
3594         /* Get the OK button */
3595         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3596         if (!dialog)
3597                 return;
3598
3599         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3600         ok_button = GTK_WIDGET (children->next->next->data);
3601         new_button = GTK_WIDGET (children->next->data);
3602         g_list_free (children);
3603
3604         /* check if folder_store is an remote account */
3605         if (TNY_IS_ACCOUNT (folder_store)) {
3606                 TnyAccount *local_account = NULL;
3607                 ModestTnyAccountStore *account_store = NULL;
3608
3609                 account_store = modest_runtime_get_account_store ();
3610                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3611
3612                 if ((gpointer) local_account != (gpointer) folder_store) {
3613                         is_local_account = FALSE;
3614                         /* New button should be dimmed on remote
3615                            account root */
3616                         new_sensitive = FALSE;
3617                 }
3618                 g_object_unref (local_account);
3619         }
3620
3621         /* Check the target folder rules */
3622         if (TNY_IS_FOLDER (folder_store)) {
3623                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3624                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3625                         ok_sensitive = FALSE;
3626                         new_sensitive = FALSE;
3627                         goto end;
3628                 }
3629         }
3630
3631         /* Check if we're moving a folder */
3632         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3633                 /* Get the widgets */
3634                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3635                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3636                 if (gtk_widget_is_focus (folder_view))
3637                         moving_folder = TRUE;
3638         }
3639
3640         if (moving_folder) {
3641                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3642
3643                 /* Get the folder to move */
3644                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3645                 
3646                 /* Check that we're not moving to the same folder */
3647                 if (TNY_IS_FOLDER (moved_folder)) {
3648                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3649                         if (parent == folder_store)
3650                                 ok_sensitive = FALSE;
3651                         g_object_unref (parent);
3652                 } 
3653
3654                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3655                         /* Do not allow to move to an account unless it's the
3656                            local folders account */
3657                         if (!is_local_account)
3658                                 ok_sensitive = FALSE;
3659                 } 
3660
3661                 if (ok_sensitive && (moved_folder == folder_store)) {
3662                         /* Do not allow to move to itself */
3663                         ok_sensitive = FALSE;
3664                 }
3665                 g_object_unref (moved_folder);
3666         } else {
3667                 TnyHeader *header = NULL;
3668                 TnyFolder *src_folder = NULL;
3669
3670                 /* Moving a message */
3671                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3672                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3673                         src_folder = tny_header_get_folder (header);
3674                         g_object_unref (header);
3675                 } else {
3676                         src_folder = 
3677                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3678                 }
3679
3680                 /* Do not allow to move the msg to the same folder */
3681                 /* Do not allow to move the msg to an account */
3682                 if ((gpointer) src_folder == (gpointer) folder_store ||
3683                     TNY_IS_ACCOUNT (folder_store))
3684                         ok_sensitive = FALSE;
3685                 g_object_unref (src_folder);
3686         }
3687
3688  end:
3689         /* Set sensitivity of the OK button */
3690         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3691         /* Set sensitivity of the NEW button */
3692         gtk_widget_set_sensitive (new_button, new_sensitive);
3693 }
3694
3695 static GtkWidget*
3696 create_move_to_dialog (GtkWindow *win,
3697                        GtkWidget *folder_view,
3698                        GtkWidget **tree_view)
3699 {
3700         GtkWidget *dialog, *scroll;
3701         GtkWidget *new_button;
3702
3703         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3704                                               GTK_WINDOW (win),
3705                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3706                                               NULL);
3707
3708         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3709         /* We do this manually so GTK+ does not associate a response ID for
3710          * the button. */
3711         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3712         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3713         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3714
3715         /* Create scrolled window */
3716         scroll = gtk_scrolled_window_new (NULL, NULL);
3717         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3718                                          GTK_POLICY_AUTOMATIC,
3719                                          GTK_POLICY_AUTOMATIC);
3720
3721         /* Create folder view */
3722         *tree_view = modest_platform_create_folder_view (NULL);
3723
3724         /* Track changes in the selection to
3725          * disable the OK button whenever "Move to" is not possible
3726          * disbale NEW button whenever New is not possible */
3727         g_signal_connect (*tree_view,
3728                           "folder_selection_changed",
3729                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3730                           win);
3731
3732         /* Listen to clicks on New button */
3733         g_signal_connect (G_OBJECT (new_button), 
3734                           "clicked", 
3735                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3736                           *tree_view);
3737
3738         /* It could happen that we're trying to move a message from a
3739            window (msg window for example) after the main window was
3740            closed, so we can not just get the model of the folder
3741            view */
3742         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3743                 const gchar *visible_id = NULL;
3744
3745                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3746                                                MODEST_FOLDER_VIEW(*tree_view));
3747
3748                 visible_id = 
3749                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3750
3751                 /* Show the same account than the one that is shown in the main window */
3752                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3753                                                                              visible_id);
3754         } else {
3755                 const gchar *active_account_name = NULL;
3756                 ModestAccountMgr *mgr = NULL;
3757                 ModestAccountData *acc_data = NULL;
3758
3759                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3760                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3761
3762                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3763                 mgr = modest_runtime_get_account_mgr ();
3764                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3765
3766                 /* Set the new visible & active account */
3767                 if (acc_data && acc_data->store_account) { 
3768                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3769                                                                                      acc_data->store_account->account_name);
3770                         modest_account_mgr_free_account_data (mgr, acc_data);
3771                 }
3772         }
3773
3774         /* Hide special folders */
3775         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3776         
3777         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3778
3779         /* Add scroll to dialog */
3780         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3781                             scroll, TRUE, TRUE, 0);
3782
3783         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3784         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3785
3786         return dialog;
3787 }
3788
3789 /*
3790  * Returns TRUE if at least one of the headers of the list belongs to
3791  * a message that has been fully retrieved.
3792  */
3793 #if 0 /* no longer in use. delete in 2007.10 */
3794 static gboolean
3795 has_retrieved_msgs (TnyList *list)
3796 {
3797         TnyIterator *iter;
3798         gboolean found = FALSE;
3799
3800         iter = tny_list_create_iterator (list);
3801         while (!tny_iterator_is_done (iter) && !found) {
3802                 TnyHeader *header;
3803                 TnyHeaderFlags flags = 0;
3804
3805                 header = TNY_HEADER (tny_iterator_get_current (iter));
3806                 if (header) {
3807                         flags = tny_header_get_flags (header);
3808                         if (flags & TNY_HEADER_FLAG_CACHED)
3809 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3810                                 found = TRUE;
3811
3812                         g_object_unref (header);
3813                 }
3814
3815                 if (!found)
3816                         tny_iterator_next (iter);
3817         }
3818         g_object_unref (iter);
3819
3820         return found;
3821 }
3822 #endif /* 0 */
3823
3824
3825 /*
3826  * Shows a confirmation dialog to the user when we're moving messages
3827  * from a remote server to the local storage. Returns the dialog
3828  * response. If it's other kind of movement then it always returns
3829  * GTK_RESPONSE_OK
3830  *
3831  * This one is used by the next functions:
3832  *      modest_ui_actions_on_paste                      - commented out
3833  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3834  */
3835 gint
3836 msgs_move_to_confirmation (GtkWindow *win,
3837                            TnyFolder *dest_folder,
3838                            gboolean delete,
3839                            TnyList *headers)
3840 {
3841         gint response = GTK_RESPONSE_OK;
3842
3843         /* return with OK if the destination is a remote folder */
3844         if (modest_tny_folder_is_remote_folder (dest_folder))
3845                 return GTK_RESPONSE_OK;
3846
3847         TnyFolder *src_folder = NULL;
3848         TnyIterator *iter = NULL;
3849         TnyHeader *header = NULL;
3850
3851         /* Get source folder */
3852         iter = tny_list_create_iterator (headers);
3853         header = TNY_HEADER (tny_iterator_get_current (iter));
3854         if (header) {
3855                 src_folder = tny_header_get_folder (header);
3856                 g_object_unref (header);
3857         }
3858         g_object_unref (iter);
3859
3860         /* if no src_folder, message may be an attahcment */
3861         if (src_folder == NULL) 
3862                 return GTK_RESPONSE_CANCEL;
3863
3864         /* If the source is a local or MMC folder */
3865         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3866                 g_object_unref (src_folder);
3867                 return GTK_RESPONSE_OK;
3868         }
3869         g_object_unref (src_folder);
3870
3871         /* now if offline we ask the user */
3872         if(connect_to_get_msg(  GTK_WINDOW (win),
3873                                         tny_list_get_length (headers)))
3874                 response = GTK_RESPONSE_OK;
3875         else
3876                 response = GTK_RESPONSE_CANCEL;
3877
3878         return response;
3879 }
3880
3881
3882
3883 static void
3884 move_to_cb (const GObject *object, gpointer user_data)
3885 {
3886         ModestMsgViewWindow *self = NULL;
3887         g_return_if_fail (GTK_IS_WIDGET (user_data));
3888         g_return_if_fail (MODEST_IS_WINDOW (object));
3889
3890         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3891                 self = MODEST_MSG_VIEW_WINDOW (object);
3892
3893                 if (!modest_msg_view_window_select_next_message (self))
3894                         if (!modest_msg_view_window_select_previous_message (self))
3895                                 /* No more messages to view, so close this window */
3896                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3897         }
3898         gtk_widget_destroy (GTK_WIDGET(user_data));
3899 }
3900
3901 void
3902 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3903                                              gpointer user_data)
3904 {
3905         ModestMainWindow *main_window = NULL;
3906         GtkWidget *folder_view = NULL;
3907         GObject *win = modest_mail_operation_get_source (mail_op);
3908         const GError *error = NULL;
3909         const gchar *message = NULL;
3910         
3911         /* Get error message */
3912         error = modest_mail_operation_get_error (mail_op);
3913         if (error != NULL && error->message != NULL) {
3914                 message = error->message;
3915         } else {
3916                 message = _("mail_in_ui_folder_move_target_error");
3917         }
3918         
3919         /* Disable next automatic folder selection */
3920         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3921                 main_window = MODEST_MAIN_WINDOW(user_data);
3922                 folder_view = modest_main_window_get_child_widget (main_window,
3923                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
3924                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));             
3925         }
3926
3927         /* Show notification dialog */
3928         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3929         g_object_unref (win);
3930 }
3931
3932 void
3933 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3934                                               gpointer user_data)
3935 {
3936         GObject *win = modest_mail_operation_get_source (mail_op);
3937         const GError *error = modest_mail_operation_get_error (mail_op);
3938
3939         g_return_if_fail (error != NULL);
3940         if (error->message != NULL)             
3941                 g_printerr ("modest: %s\n", error->message);
3942         else
3943                 g_printerr ("modest: unkonw error on send&receive operation");
3944
3945         /* Show error message */
3946 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3947 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3948 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3949 /*      else  */
3950 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3951 /*                                                      _CS("sfil_ib_unable_to_send")); */
3952         g_object_unref (win);
3953 }
3954
3955 static void
3956 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3957                        TnyHeader *header, 
3958                        TnyMsg *msg, 
3959                        gpointer user_data)
3960 {
3961         TnyList *parts;
3962         TnyIterator *iter;
3963         gint pending_purges = 0;
3964         gboolean some_purged = FALSE;
3965         ModestWindow *win = MODEST_WINDOW (user_data);
3966         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3967
3968         /* If there was any error */
3969         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3970                 modest_window_mgr_unregister_header (mgr, header);
3971                 return;
3972         }
3973
3974         /* Once the message has been retrieved for purging, we check if
3975          * it's all ok for purging */
3976
3977         parts = tny_simple_list_new ();
3978         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3979         iter = tny_list_create_iterator (parts);
3980
3981         while (!tny_iterator_is_done (iter)) {
3982                 TnyMimePart *part;
3983                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3984                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3985                         if (tny_mime_part_is_purged (part))
3986                                 some_purged = TRUE;
3987                         else
3988                                 pending_purges++;
3989                 }
3990
3991                 if (part)
3992                         g_object_unref (part);
3993
3994                 tny_iterator_next (iter);
3995         }
3996
3997         if (pending_purges>0) {
3998                 gint response;
3999                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4000
4001                 if (response == GTK_RESPONSE_OK) {
4002                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4003                         tny_iterator_first (iter);
4004                         while (!tny_iterator_is_done (iter)) {
4005                                 TnyMimePart *part;
4006                                 
4007                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4008                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4009                                         tny_mime_part_set_purged (part);
4010
4011                                 if (part)
4012                                         g_object_unref (part);
4013
4014                                 tny_iterator_next (iter);
4015                         }
4016                         
4017                         tny_msg_rewrite_cache (msg);
4018                 }
4019         } else {
4020                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4021         }
4022
4023         /* remove attachments */
4024         tny_iterator_first (iter);
4025         while (!tny_iterator_is_done (iter)) {
4026                 TnyMimePart *part;
4027                         
4028                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4029                 if (part) {
4030                         /* One for the reference given by tny_iterator_get_current(): */
4031                         g_object_unref (part);
4032
4033                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
4034                          * Otherwise, this seems useless. */
4035                 }
4036
4037                 tny_iterator_next (iter);
4038         }
4039         modest_window_mgr_unregister_header (mgr, header);
4040
4041         g_object_unref (iter);
4042         g_object_unref (parts);
4043 }
4044
4045 static void
4046 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4047                                                      ModestMainWindow *win)
4048 {
4049         GtkWidget *header_view;
4050         TnyList *header_list;
4051         TnyIterator *iter;
4052         TnyHeader *header;
4053         TnyHeaderFlags flags;
4054         ModestWindow *msg_view_window =  NULL;
4055         gboolean found;
4056
4057         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4058
4059         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4060                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4061
4062         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4063
4064         if (tny_list_get_length (header_list) == 1) {
4065                 iter = tny_list_create_iterator (header_list);
4066                 header = TNY_HEADER (tny_iterator_get_current (iter));
4067                 g_object_unref (iter);
4068         } else {
4069                 return;
4070         }
4071
4072         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4073                                                           header, &msg_view_window);
4074         flags = tny_header_get_flags (header);
4075         if (!(flags & TNY_HEADER_FLAG_CACHED))
4076                 return;
4077         if (found) {
4078                 if (msg_view_window != NULL) 
4079                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4080                 else {
4081                         /* do nothing; uid was registered before, so window is probably on it's way */
4082                         g_warning ("debug: header %p has already been registered", header);
4083                 }
4084         } else {
4085                 ModestMailOperation *mail_op = NULL;
4086                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4087                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4088                                                                          G_OBJECT (win),
4089                                                                          modest_ui_actions_get_msgs_full_error_handler,
4090                                                                          NULL);
4091                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4092                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4093                 
4094                 g_object_unref (mail_op);
4095         }
4096         if (header)
4097                 g_object_unref (header);
4098         if (header_list)
4099                 g_object_unref (header_list);
4100 }
4101
4102 /**
4103  * Utility function that transfer messages from both the main window
4104  * and the msg view window when using the "Move to" dialog
4105  */
4106 static void
4107 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4108                                               ModestWindow *win)
4109 {
4110         TnyList *headers = NULL;
4111         TnyAccount *dst_account = NULL;
4112         const gchar *proto_str = NULL;
4113         gboolean dst_is_pop = FALSE;
4114
4115         if (!TNY_IS_FOLDER (dst_folder)) {
4116                 modest_platform_information_banner (GTK_WIDGET (win),
4117                                                     NULL,
4118                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4119                 return;
4120         }
4121
4122         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4123         proto_str = tny_account_get_proto (dst_account);
4124
4125         /* tinymail will return NULL for local folders it seems */
4126         dst_is_pop = proto_str &&
4127                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4128                  MODEST_PROTOCOL_STORE_POP);
4129
4130         g_object_unref (dst_account);
4131
4132         /* Get selected headers */
4133         headers = get_selected_headers (MODEST_WINDOW (win));
4134
4135         if (dst_is_pop) {
4136                 modest_platform_information_banner (GTK_WIDGET (win),
4137                                                     NULL,
4138                                                     ngettext("mail_in_ui_folder_move_target_error",
4139                                                              "mail_in_ui_folder_move_targets_error",
4140                                                              tny_list_get_length (headers)));
4141                 g_object_unref (headers);
4142                 return;
4143         }
4144
4145         GtkWidget *inf_note;
4146         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4147                                                      _CS("ckct_nw_pasting"));
4148         if (inf_note != NULL)  {
4149                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4150                 gtk_widget_show (GTK_WIDGET(inf_note));
4151         }
4152
4153         ModestMailOperation *mail_op = 
4154                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4155                                                                G_OBJECT(win),
4156                                                                modest_ui_actions_move_folder_error_handler,
4157                                                                NULL);
4158         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4159                                          mail_op);
4160
4161         modest_mail_operation_xfer_msgs (mail_op, 
4162                                          headers,
4163                                          TNY_FOLDER (dst_folder),
4164                                          TRUE,
4165                                          move_to_cb,
4166                                          inf_note);
4167
4168         g_object_unref (G_OBJECT (mail_op));
4169         g_object_unref (headers);
4170 }
4171
4172 /*
4173  * UI handler for the "Move to" action when invoked from the
4174  * ModestMainWindow
4175  */
4176 static void 
4177 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4178                                           GtkWidget *folder_view,
4179                                           TnyFolderStore *dst_folder,
4180                                           ModestMainWindow *win)
4181 {
4182         ModestHeaderView *header_view = NULL;
4183         ModestMailOperation *mail_op = NULL;
4184         TnyFolderStore *src_folder;
4185         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4186
4187         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4188
4189         /* Get the source folder */
4190         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4191
4192         /* Get header view */
4193         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4194
4195         /* Get folder or messages to transfer */
4196         if (gtk_widget_is_focus (folder_view)) {
4197                 GtkTreeSelection *sel;
4198                 gboolean do_xfer = TRUE;
4199
4200                 /* Allow only to transfer folders to the local root folder */
4201                 if (TNY_IS_ACCOUNT (dst_folder) && 
4202                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4203                         do_xfer = FALSE;
4204                 } else if (!TNY_IS_FOLDER (src_folder)) {
4205                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4206                         do_xfer = FALSE;
4207                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4208                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4209                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4210                                 do_xfer = FALSE;
4211                         }
4212                 }
4213
4214                 if (do_xfer) {
4215                         GtkWidget *inf_note;
4216                         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4217                                                                      _CS("ckct_nw_pasting"));
4218                         if (inf_note != NULL)  {
4219                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4220                                 gtk_widget_show (GTK_WIDGET(inf_note));
4221                         }
4222                         /* Clean folder on header view before moving it */
4223                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4224                         gtk_tree_selection_unselect_all (sel);
4225
4226                         mail_op =
4227                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4228                                                                          G_OBJECT(win),
4229                                                                          modest_ui_actions_move_folder_error_handler,
4230                                                                          win);
4231                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4232                                                          mail_op);
4233
4234                         /* Select *after* the changes */
4235                         /* TODO: this function hangs UI after transfer */ 
4236 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4237 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4238                         
4239                         modest_mail_operation_xfer_folder (mail_op,
4240                                                            TNY_FOLDER (src_folder),
4241                                                            dst_folder,
4242                                                            TRUE, move_to_cb, inf_note);
4243                         /* Unref mail operation */
4244                         g_object_unref (G_OBJECT (mail_op));
4245                 }
4246         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4247                 gboolean do_xfer = TRUE;
4248                 /* Ask for confirmation if the source folder is remote and we're not connected */
4249                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4250                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4251                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4252                                 guint num_headers = tny_list_get_length(headers);
4253                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4254                                         do_xfer = FALSE;
4255                                 }
4256                         }
4257                         g_object_unref(headers);
4258                 }
4259                 if (do_xfer) /* Transfer messages */
4260                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4261         }
4262
4263     if (src_folder)
4264         g_object_unref (src_folder);
4265 }
4266
4267
4268 /*
4269  * UI handler for the "Move to" action when invoked from the
4270  * ModestMsgViewWindow
4271  */
4272 static void 
4273 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4274                                               TnyFolderStore *dst_folder,
4275                                               ModestMsgViewWindow *win)
4276 {
4277         TnyHeader *header = NULL;
4278         TnyFolderStore *src_folder;
4279
4280         /* Create header list */
4281         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4282         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4283         g_object_unref (header);
4284
4285         /* Transfer the message if online or confirmed by the user */
4286         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4287             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4288                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4289         }
4290
4291         g_object_unref (src_folder);
4292 }
4293
4294 void 
4295 modest_ui_actions_on_move_to (GtkAction *action, 
4296                               ModestWindow *win)
4297 {
4298         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4299         gint result = 0;
4300         TnyFolderStore *dst_folder = NULL;
4301         ModestMainWindow *main_window;
4302
4303         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4304                           MODEST_IS_MSG_VIEW_WINDOW (win));
4305
4306         /* Get the main window if exists */
4307         if (MODEST_IS_MAIN_WINDOW (win))
4308                 main_window = MODEST_MAIN_WINDOW (win);
4309         else
4310                 main_window = 
4311                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4312
4313         /* Get the folder view widget if exists */
4314         if (main_window)
4315                 folder_view = modest_main_window_get_child_widget (main_window,
4316                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4317         else
4318                 folder_view = NULL;
4319
4320         /* Create and run the dialog */
4321         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4322         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4323         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4324         result = gtk_dialog_run (GTK_DIALOG(dialog));
4325         g_object_ref (tree_view);
4326         gtk_widget_destroy (dialog);
4327
4328         if (result != GTK_RESPONSE_ACCEPT)
4329                 return;
4330
4331         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4332         /* Do window specific stuff */
4333         if (MODEST_IS_MAIN_WINDOW (win)) {
4334                 modest_ui_actions_on_main_window_move_to (action,
4335                                                           folder_view,
4336                                                           dst_folder,
4337                                                           MODEST_MAIN_WINDOW (win));
4338         } else {
4339                 modest_ui_actions_on_msg_view_window_move_to (action,
4340                                                               dst_folder,
4341                                                               MODEST_MSG_VIEW_WINDOW (win));
4342         }
4343
4344         if (dst_folder)
4345                 g_object_unref (dst_folder);
4346 }
4347
4348 /*
4349  * Calls #HeadersFunc for each header already selected in the main
4350  * window or the message currently being shown in the msg view window
4351  */
4352 static void
4353 do_headers_action (ModestWindow *win, 
4354                    HeadersFunc func,
4355                    gpointer user_data)
4356 {
4357         TnyList *headers_list = NULL;
4358         TnyIterator *iter = NULL;
4359         TnyHeader *header = NULL;
4360         TnyFolder *folder = NULL;
4361
4362         /* Get headers */
4363         headers_list = get_selected_headers (win);
4364         if (!headers_list)
4365                 return;
4366
4367         /* Get the folder */
4368         iter = tny_list_create_iterator (headers_list);
4369         header = TNY_HEADER (tny_iterator_get_current (iter));
4370         if (header) {
4371                 folder = tny_header_get_folder (header);
4372                 g_object_unref (header);
4373         }
4374
4375         /* Call the function for each header */
4376         while (!tny_iterator_is_done (iter)) {
4377                 header = TNY_HEADER (tny_iterator_get_current (iter));
4378                 func (header, win, user_data);
4379                 g_object_unref (header);
4380                 tny_iterator_next (iter);
4381         }
4382
4383         /* Trick: do a poke status in order to speed up the signaling
4384            of observers */
4385         tny_folder_poke_status (folder);
4386
4387         /* Frees */
4388         g_object_unref (folder);
4389         g_object_unref (iter);
4390         g_object_unref (headers_list);
4391 }
4392
4393 void 
4394 modest_ui_actions_view_attachment (GtkAction *action,
4395                                    ModestWindow *window)
4396 {
4397         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4398                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4399         } else {
4400                 /* not supported window for this action */
4401                 g_return_if_reached ();
4402         }
4403 }
4404
4405 void
4406 modest_ui_actions_save_attachments (GtkAction *action,
4407                                     ModestWindow *window)
4408 {
4409         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4410                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4411         } else {
4412                 /* not supported window for this action */
4413                 g_return_if_reached ();
4414         }
4415 }
4416
4417 void
4418 modest_ui_actions_remove_attachments (GtkAction *action,
4419                                       ModestWindow *window)
4420 {
4421         if (MODEST_IS_MAIN_WINDOW (window)) {
4422                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4423         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4424                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4425         } else {
4426                 /* not supported window for this action */
4427                 g_return_if_reached ();
4428         }
4429 }
4430
4431 void 
4432 modest_ui_actions_on_settings (GtkAction *action, 
4433                                ModestWindow *win)
4434 {
4435         GtkWidget *dialog;
4436
4437         dialog = modest_platform_get_global_settings_dialog ();
4438         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4439         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4440         gtk_widget_show_all (dialog);
4441
4442         gtk_dialog_run (GTK_DIALOG (dialog));
4443
4444         gtk_widget_destroy (dialog);
4445 }
4446
4447 void 
4448 modest_ui_actions_on_help (GtkAction *action, 
4449                            ModestWindow *win)
4450 {
4451         const gchar *help_id = NULL;
4452
4453         if (MODEST_IS_MAIN_WINDOW (win)) {
4454                 GtkWidget *folder_view;
4455                 TnyFolderStore *folder_store;
4456                 
4457                 /* Get selected folder */
4458                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4459                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4460                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4461
4462                 /* Switch help_id */
4463                 if (TNY_IS_FOLDER (folder_store)) {
4464                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4465                         case TNY_FOLDER_TYPE_NORMAL:
4466                                 help_id = "applications_email_managefolders";
4467                                 break;
4468                         case TNY_FOLDER_TYPE_INBOX:
4469                                 help_id = "applications_email_inbox";
4470                                 break;
4471                         case TNY_FOLDER_TYPE_OUTBOX:
4472                                 help_id = "applications_email_outbox";
4473                                 break;
4474                         case TNY_FOLDER_TYPE_SENT:
4475                                 help_id = "applications_email_sent";
4476                                 break;
4477                         case TNY_FOLDER_TYPE_DRAFTS:
4478                                 help_id = "applications_email_drafts";
4479                                 break;
4480                         case TNY_FOLDER_TYPE_ARCHIVE:
4481                                 help_id = "applications_email_managefolders";
4482                                 break;
4483                         default:
4484                                 help_id = "applications_email_managefolders";
4485                         }
4486                 } else {
4487                         help_id = "applications_email_mainview";
4488                 }
4489                 g_object_unref (folder_store);
4490         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4491                 help_id = "applications_email_viewer";
4492         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4493                 help_id = "applications_email_editor";
4494
4495         modest_platform_show_help (GTK_WINDOW (win), help_id);
4496 }
4497
4498 void 
4499 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4500                                             ModestWindow *window)
4501 {
4502         ModestMailOperation *mail_op;
4503         TnyList *headers;
4504
4505         /* Get headers */
4506         headers = get_selected_headers (window);
4507         if (!headers)
4508                 return;
4509
4510         /* Create mail operation */
4511         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4512                                                                  G_OBJECT (window),
4513                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4514                                                                  NULL);
4515         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4516         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4517
4518         /* Frees */
4519         g_object_unref (headers);
4520         g_object_unref (mail_op);
4521 }
4522
4523 void
4524 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4525                                           ModestWindow *window)
4526 {
4527         g_return_if_fail (MODEST_IS_WINDOW (window));
4528         
4529         /* Update dimmed */     
4530         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4531 }
4532
4533 void
4534 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4535                                           ModestWindow *window)
4536 {
4537         g_return_if_fail (MODEST_IS_WINDOW (window));
4538
4539         /* Update dimmed */     
4540         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4541 }
4542
4543 void
4544 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4545                                           ModestWindow *window)
4546 {
4547         g_return_if_fail (MODEST_IS_WINDOW (window));
4548
4549         /* Update dimmed */     
4550         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4551 }
4552
4553 void
4554 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4555                                             ModestWindow *window)
4556 {
4557         g_return_if_fail (MODEST_IS_WINDOW (window));
4558
4559         /* Update dimmed */     
4560         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4561 }
4562
4563 void
4564 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4565                                           ModestWindow *window)
4566 {
4567         g_return_if_fail (MODEST_IS_WINDOW (window));
4568
4569         /* Update dimmed */     
4570         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4571 }
4572
4573 void
4574 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4575                                           ModestWindow *window)
4576 {
4577         g_return_if_fail (MODEST_IS_WINDOW (window));
4578
4579         /* Update dimmed */     
4580         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4581 }
4582
4583 void
4584 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4585                                                  ModestWindow *window)
4586 {
4587         g_return_if_fail (MODEST_IS_WINDOW (window));
4588
4589         /* Update dimmed */     
4590         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4591 }
4592
4593 void
4594 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4595                                                      ModestWindow *window)
4596 {
4597         g_return_if_fail (MODEST_IS_WINDOW (window));
4598
4599         /* Update dimmed */     
4600         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4601 }
4602
4603 void
4604 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4605                                                      ModestWindow *window)
4606 {
4607         g_return_if_fail (MODEST_IS_WINDOW (window));
4608
4609         /* Update dimmed */     
4610         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4611 }
4612
4613 void
4614 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4615 {
4616         g_return_if_fail (MODEST_IS_WINDOW (window));
4617
4618         /* Update dimmed */     
4619         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4620 }
4621
4622 void
4623 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4624 {
4625         g_return_if_fail (MODEST_IS_WINDOW (window));
4626
4627         modest_platform_show_search_messages (GTK_WINDOW (window));
4628 }
4629
4630 void     
4631 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4632 {
4633         g_return_if_fail (MODEST_IS_WINDOW (win));
4634         modest_platform_show_addressbook (GTK_WINDOW (win));
4635 }
4636
4637
4638 void
4639 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4640                                           ModestWindow *window)
4641 {
4642         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4643
4644         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4645 }
4646
4647 static void 
4648 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4649                                    ModestMailOperationState *state,
4650                                    gpointer user_data)
4651 {
4652         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4653
4654         /* Set send/receive operation finished */       
4655         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4656                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4657         
4658 }
4659
4660
4661 void 
4662 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4663                                                 TnyHeader *header, 
4664                                                 TnyMsg *msg, 
4665                                                 GError *err, 
4666                                                 gpointer user_data)
4667 {
4668         const gchar* server_name = NULL;
4669         TnyTransportAccount *server_account;
4670         gchar *message = NULL;
4671
4672         /* Don't show anything if the user cancelled something */
4673         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4674                 return;
4675
4676         /* Get the server name: */
4677         server_account = 
4678                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4679         if (server_account) {
4680                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4681                         
4682                 g_object_unref (server_account);
4683                 server_account = NULL;
4684         }
4685         
4686         g_return_if_fail (server_name);
4687
4688         /* Show the appropriate message text for the GError: */
4689         switch (err->code) {
4690         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4691                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4692                 break;
4693         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4694                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4695                 break;
4696         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4697                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4698                 break;
4699         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4700                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4701                 break;
4702         default:
4703                 g_return_if_reached ();
4704         }
4705         
4706         /* TODO if the username or the password where not defined we
4707            should show the Accounts Settings dialog or the Connection
4708            specific SMTP server window */
4709
4710         modest_maemo_show_information_note_and_forget (NULL, message);
4711         g_free (message);
4712 }
4713
4714 void
4715 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4716                                                 gchar *msg_id, 
4717                                                 guint status,
4718                                                 gpointer user_data)
4719 {
4720         ModestMainWindow *main_window = NULL;
4721         ModestWindowMgr *mgr = NULL;
4722         GtkWidget *folder_view = NULL, *header_view = NULL;
4723         TnyFolderStore *selected_folder = NULL;
4724         TnyFolderType folder_type;
4725
4726         mgr = modest_runtime_get_window_mgr ();
4727         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
4728
4729         if (!main_window)
4730                 return;
4731
4732         /* Check if selected folder is OUTBOX */
4733         folder_view = modest_main_window_get_child_widget (main_window,
4734                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4735         header_view = modest_main_window_get_child_widget (main_window,
4736                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4737
4738         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4739         if (!TNY_IS_FOLDER (selected_folder)) 
4740                 goto frees;
4741
4742         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4743 #if GTK_CHECK_VERSION(2, 8, 0) 
4744         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4745         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4746                 GtkTreeViewColumn *tree_column;
4747
4748                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4749                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4750                 gtk_tree_view_column_queue_resize (tree_column);
4751         }
4752 #else
4753         gtk_widget_queue_draw (header_view);
4754 #endif          
4755         
4756         /* Free */
4757  frees:
4758         if (selected_folder != NULL)
4759                 g_object_unref (selected_folder);
4760 }