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