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