* src/modest-ui-actions.c
[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
2464         if (!folder)
2465                 return;
2466
2467         if (TNY_IS_FOLDER (folder)) {
2468                 gchar *folder_name;
2469                 gint response;
2470                 const gchar *current_name;
2471                 TnyFolderStore *parent;
2472                 gboolean do_rename = TRUE;
2473
2474                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2475                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2476                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2477                                                                      parent, current_name, 
2478                                                                      &folder_name);
2479                 g_object_unref (parent);
2480
2481                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2482                         do_rename = FALSE;
2483                 } else if (modest_platform_is_network_folderstore(folder) &&
2484                            !tny_device_is_online (modest_runtime_get_device())) {
2485                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2486                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2487                         g_object_unref(account);
2488                 }
2489
2490                 if (do_rename) {
2491                         ModestMailOperation *mail_op;
2492                         GtkTreeSelection *sel = NULL;
2493
2494                         mail_op = 
2495                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2496                                                                                G_OBJECT(main_window),
2497                                                                                modest_ui_actions_rename_folder_error_handler,
2498                                                                                main_window);
2499
2500                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2501                                                          mail_op);
2502
2503                         /* Clear the headers view */
2504                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2505                         gtk_tree_selection_unselect_all (sel);
2506
2507                         /* Select *after* the changes */
2508                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2509                                                           TNY_FOLDER(folder), TRUE);
2510
2511                         modest_mail_operation_rename_folder (mail_op,
2512                                                              TNY_FOLDER (folder),
2513                                                              (const gchar *) folder_name);
2514
2515                         g_object_unref (mail_op);
2516                         g_free (folder_name);
2517                 }
2518         }
2519         g_object_unref (folder);
2520 }
2521
2522 static void
2523 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2524                                                gpointer user_data)
2525 {
2526         GObject *win = modest_mail_operation_get_source (mail_op);
2527
2528         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2529                                                 _("mail_in_ui_folder_delete_error"));
2530         g_object_unref (win);
2531 }
2532
2533 static void
2534 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2535 {
2536         TnyFolderStore *folder;
2537         GtkWidget *folder_view;
2538         gint response;
2539         gchar *message;
2540         gboolean do_delete = TRUE;
2541
2542         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2543
2544         folder_view = modest_main_window_get_child_widget (main_window,
2545                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2546         if (!folder_view)
2547                 return;
2548
2549         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2550
2551         /* Show an error if it's an account */
2552         if (!TNY_IS_FOLDER (folder)) {
2553                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2554                                                         _("mail_in_ui_folder_delete_error"));
2555                 g_object_unref (G_OBJECT (folder));
2556                 return ;
2557         }
2558
2559         /* Ask the user */      
2560         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2561                                     tny_folder_get_name (TNY_FOLDER (folder)));
2562         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2563                                                             (const gchar *) message);
2564         g_free (message);
2565
2566         if (response != GTK_RESPONSE_OK) {
2567                 do_delete = FALSE;
2568         } else if (modest_platform_is_network_folderstore(folder) &&
2569                    !tny_device_is_online (modest_runtime_get_device())) {
2570                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2571                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2572                 g_object_unref(account);
2573         }
2574
2575         if (do_delete) {
2576                 ModestMailOperation *mail_op;
2577                 GtkTreeSelection *sel;
2578
2579                 /* Unselect the folder before deleting it to free the headers */
2580                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2581                 gtk_tree_selection_unselect_all (sel);
2582
2583                 /* Create the mail operation */
2584                 mail_op =
2585                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2586                                                                        G_OBJECT(main_window),
2587                                                                        modest_ui_actions_delete_folder_error_handler,
2588                                                                        NULL);
2589
2590                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2591                                                  mail_op);
2592                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2593                 g_object_unref (G_OBJECT (mail_op));
2594         }
2595
2596         g_object_unref (G_OBJECT (folder));
2597 }
2598
2599 void 
2600 modest_ui_actions_on_delete_folder (GtkAction *action,
2601                                      ModestMainWindow *main_window)
2602 {
2603         GtkWidget *folder_view;
2604         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2605
2606         delete_folder (main_window, FALSE);
2607         folder_view = modest_main_window_get_child_widget (main_window,
2608                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2609         if (!folder_view)
2610                 return;
2611         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2612 }
2613
2614 void 
2615 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2616 {
2617         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2618         
2619         delete_folder (main_window, TRUE);
2620 }
2621
2622
2623 static void
2624 show_error (GtkWidget *parent_widget, const gchar* text)
2625 {
2626         hildon_banner_show_information(parent_widget, NULL, text);
2627         
2628 #if 0
2629         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2630         /*
2631           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2632           (GtkDialogFlags)0,
2633           GTK_MESSAGE_ERROR,
2634           GTK_BUTTONS_OK,
2635           text ));
2636         */
2637                  
2638         gtk_dialog_run (dialog);
2639         gtk_widget_destroy (GTK_WIDGET (dialog));
2640 #endif
2641 }
2642
2643 void
2644 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2645                                          const gchar* server_account_name,
2646                                          gchar **username,
2647                                          gchar **password, 
2648                                          gboolean *cancel, 
2649                                          gboolean *remember,
2650                                          ModestMainWindow *main_window)
2651 {
2652         g_return_if_fail(server_account_name);
2653         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2654         
2655         /* Initalize output parameters: */
2656         if (cancel)
2657                 *cancel = FALSE;
2658                 
2659         if (remember)
2660                 *remember = TRUE;
2661                 
2662 #ifdef MODEST_PLATFORM_MAEMO
2663         /* Maemo uses a different (awkward) button order,
2664          * It should probably just use gtk_alternative_dialog_button_order ().
2665          */
2666         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2667                                               NULL,
2668                                               GTK_DIALOG_MODAL,
2669                                               _("mcen_bd_dialog_ok"),
2670                                               GTK_RESPONSE_ACCEPT,
2671                                               _("mcen_bd_dialog_cancel"),
2672                                               GTK_RESPONSE_REJECT,
2673                                               NULL);
2674 #else
2675         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2676                                               NULL,
2677                                               GTK_DIALOG_MODAL,
2678                                               GTK_STOCK_CANCEL,
2679                                               GTK_RESPONSE_REJECT,
2680                                               GTK_STOCK_OK,
2681                                               GTK_RESPONSE_ACCEPT,
2682                                               NULL);
2683 #endif /* MODEST_PLATFORM_MAEMO */
2684
2685         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2686         
2687         gchar *server_name = modest_server_account_get_hostname (
2688                 modest_runtime_get_account_mgr(), server_account_name);
2689         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2690                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2691                 *cancel = TRUE;
2692                 return;
2693         }
2694         
2695         /* This causes a warning because the logical ID has no %s in it, 
2696          * though the translation does, but there is not much we can do about that: */
2697         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2698         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2699                             FALSE, FALSE, 0);
2700         g_free (txt);
2701         g_free (server_name);
2702         server_name = NULL;
2703
2704         /* username: */
2705         gchar *initial_username = modest_server_account_get_username (
2706                 modest_runtime_get_account_mgr(), server_account_name);
2707         
2708         GtkWidget *entry_username = gtk_entry_new ();
2709         if (initial_username)
2710                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2711         /* Dim this if a connection has ever succeeded with this username,
2712          * as per the UI spec: */
2713         const gboolean username_known = 
2714                 modest_server_account_get_username_has_succeeded(
2715                         modest_runtime_get_account_mgr(), server_account_name);
2716         gtk_widget_set_sensitive (entry_username, !username_known);
2717         
2718 #ifdef MODEST_PLATFORM_MAEMO
2719         /* Auto-capitalization is the default, so let's turn it off: */
2720         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2721         
2722         /* Create a size group to be used by all captions.
2723          * Note that HildonCaption does not create a default size group if we do not specify one.
2724          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2725         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2726         
2727         GtkWidget *caption = hildon_caption_new (sizegroup, 
2728                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2729         gtk_widget_show (entry_username);
2730         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2731                 FALSE, FALSE, MODEST_MARGIN_HALF);
2732         gtk_widget_show (caption);
2733 #else 
2734         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2735                             TRUE, FALSE, 0);
2736 #endif /* MODEST_PLATFORM_MAEMO */      
2737                             
2738         /* password: */
2739         GtkWidget *entry_password = gtk_entry_new ();
2740         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2741         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2742         
2743 #ifdef MODEST_PLATFORM_MAEMO
2744         /* Auto-capitalization is the default, so let's turn it off: */
2745         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2746                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2747         
2748         caption = hildon_caption_new (sizegroup, 
2749                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2750         gtk_widget_show (entry_password);
2751         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2752                 FALSE, FALSE, MODEST_MARGIN_HALF);
2753         gtk_widget_show (caption);
2754         g_object_unref (sizegroup);
2755 #else 
2756         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2757                             TRUE, FALSE, 0);
2758 #endif /* MODEST_PLATFORM_MAEMO */      
2759                                 
2760 /* This is not in the Maemo UI spec:
2761         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2762         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2763                             TRUE, FALSE, 0);
2764 */
2765
2766         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2767         
2768         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2769                 if (username) {
2770                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2771                         
2772                         modest_server_account_set_username (
2773                                  modest_runtime_get_account_mgr(), server_account_name, 
2774                                  *username);
2775                                  
2776                         const gboolean username_was_changed = 
2777                                 (strcmp (*username, initial_username) != 0);
2778                         if (username_was_changed) {
2779                                 g_warning ("%s: tinymail does not yet support changing the "
2780                                         "username in the get_password() callback.\n", __FUNCTION__);
2781                         }
2782                 }
2783                         
2784                 if (password) {
2785                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2786                         
2787                         /* We do not save the password in the configuration, 
2788                          * because this function is only called for passwords that should 
2789                          * not be remembered:
2790                         modest_server_account_set_password (
2791                                  modest_runtime_get_account_mgr(), server_account_name, 
2792                                  *password);
2793                         */
2794                 }
2795                 
2796                 if (cancel)
2797                         *cancel   = FALSE;
2798                         
2799         } else {
2800                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2801                 
2802                 if (username)
2803                         *username = NULL;
2804                         
2805                 if (password)
2806                         *password = NULL;
2807                         
2808                 if (cancel)
2809                         *cancel   = TRUE;
2810         }
2811
2812 /* This is not in the Maemo UI spec:
2813         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2814                 *remember = TRUE;
2815         else
2816                 *remember = FALSE;
2817 */
2818
2819         gtk_widget_destroy (dialog);
2820         
2821         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2822 }
2823
2824 void
2825 modest_ui_actions_on_cut (GtkAction *action,
2826                           ModestWindow *window)
2827 {
2828         GtkWidget *focused_widget;
2829         GtkClipboard *clipboard;
2830
2831         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2832         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2833         if (GTK_IS_EDITABLE (focused_widget)) {
2834                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2835                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2836                 gtk_clipboard_store (clipboard);
2837         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2838                 GtkTextBuffer *buffer;
2839
2840                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2841                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2842                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2843                 gtk_clipboard_store (clipboard);
2844         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2845                 TnyList *header_list = modest_header_view_get_selected_headers (
2846                                 MODEST_HEADER_VIEW (focused_widget));
2847                 gboolean continue_download = FALSE;
2848                 gint num_of_unc_msgs;
2849
2850                 num_of_unc_msgs = header_list_count_uncached_msgs(
2851                                 header_list, GTK_WINDOW (window));
2852
2853                 if (num_of_unc_msgs)
2854                         continue_download = connect_to_get_msg(
2855                                                                 GTK_WINDOW (window),
2856                                                                 num_of_unc_msgs);
2857
2858                 if (num_of_unc_msgs == 0 || continue_download) {
2859 /*                      modest_platform_information_banner (
2860                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2861                         modest_header_view_cut_selection (
2862                                         MODEST_HEADER_VIEW (focused_widget));
2863                 }
2864
2865                 g_object_unref (header_list);
2866         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2867                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2868         }
2869 }
2870
2871 void
2872 modest_ui_actions_on_copy (GtkAction *action,
2873                            ModestWindow *window)
2874 {
2875         GtkClipboard *clipboard;
2876         GtkWidget *focused_widget;
2877         gboolean copied = TRUE;
2878
2879         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2880         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2881
2882         if (GTK_IS_LABEL (focused_widget)) {
2883                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2884                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2885                 gtk_clipboard_store (clipboard);
2886         } else if (GTK_IS_EDITABLE (focused_widget)) {
2887                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2888                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2889                 gtk_clipboard_store (clipboard);
2890         } else if (GTK_IS_HTML (focused_widget)) {
2891                 gtk_html_copy (GTK_HTML (focused_widget));
2892                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2893                 gtk_clipboard_store (clipboard);
2894         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2895                 GtkTextBuffer *buffer;
2896                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2897                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2898                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2899                 gtk_clipboard_store (clipboard);
2900         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2901                 TnyList *header_list = modest_header_view_get_selected_headers (
2902                                 MODEST_HEADER_VIEW (focused_widget));
2903                 gboolean continue_download = FALSE;
2904                 gint num_of_unc_msgs;
2905
2906                 num_of_unc_msgs = header_list_count_uncached_msgs(
2907                                                                 header_list,
2908                                                                 GTK_WINDOW (window));
2909
2910                 if (num_of_unc_msgs)
2911                         continue_download = connect_to_get_msg(
2912                                                                 GTK_WINDOW (window),
2913                                                                 num_of_unc_msgs);
2914
2915                 if (num_of_unc_msgs == 0 || continue_download) {
2916                         modest_platform_information_banner (
2917                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2918                         modest_header_view_copy_selection (
2919                                         MODEST_HEADER_VIEW (focused_widget));
2920                 } else
2921                         copied = FALSE;
2922
2923                 g_object_unref (header_list);
2924
2925         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2926                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2927         }
2928
2929         /* Show information banner if there was a copy to clipboard */
2930         if(copied)
2931                 modest_platform_information_banner (
2932                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2933 }
2934
2935 void
2936 modest_ui_actions_on_undo (GtkAction *action,
2937                            ModestWindow *window)
2938 {
2939         ModestEmailClipboard *clipboard = NULL;
2940
2941         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2942                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2943         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2944                 /* Clear clipboard source */
2945                 clipboard = modest_runtime_get_email_clipboard ();
2946                 modest_email_clipboard_clear (clipboard);               
2947         }
2948         else {
2949                 g_return_if_reached ();
2950         }
2951 }
2952
2953 void
2954 modest_ui_actions_on_redo (GtkAction *action,
2955                            ModestWindow *window)
2956 {
2957         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2958                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2959         }
2960         else {
2961                 g_return_if_reached ();
2962         }
2963 }
2964
2965
2966 static void
2967 paste_msgs_cb (const GObject *object, gpointer user_data)
2968 {
2969         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2970         g_return_if_fail (GTK_IS_WIDGET (user_data));
2971         
2972         /* destroy information note */
2973         gtk_widget_destroy (GTK_WIDGET(user_data));
2974 }
2975
2976 static void
2977 paste_as_attachment_free (gpointer data)
2978 {
2979         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2980
2981         gtk_widget_destroy (helper->banner);
2982         g_object_unref (helper->banner);
2983         g_free (helper);
2984 }
2985
2986 static void
2987 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2988                             TnyHeader *header,
2989                             TnyMsg *msg,
2990                             gpointer userdata)
2991 {
2992         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2993         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2994
2995         if (msg == NULL)
2996                 return;
2997
2998         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2999         
3000 }
3001
3002 void
3003 modest_ui_actions_on_paste (GtkAction *action,
3004                             ModestWindow *window)
3005 {
3006         GtkWidget *focused_widget = NULL;
3007         GtkWidget *inf_note = NULL;
3008         ModestMailOperation *mail_op = NULL;
3009
3010         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3011         if (GTK_IS_EDITABLE (focused_widget)) {
3012                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3013         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3014                 ModestEmailClipboard *e_clipboard = NULL;
3015                 e_clipboard = modest_runtime_get_email_clipboard ();
3016                 if (modest_email_clipboard_cleared (e_clipboard)) {
3017                         GtkTextBuffer *buffer;
3018                         GtkClipboard *clipboard;
3019
3020                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3021                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3022                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3023                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3024                         ModestMailOperation *mail_op;
3025                         TnyFolder *src_folder;
3026                         TnyList *data;
3027                         gboolean delete;
3028                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3029                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3030                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3031                                                                            _CS("ckct_nw_pasting"));
3032                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3033                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3034                                                              G_OBJECT (window));
3035                         if (helper->banner != NULL) {
3036                                 g_object_ref (G_OBJECT (helper->banner));
3037                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3038                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3039                         }
3040
3041                         if (data != NULL) {
3042                                 modest_mail_operation_get_msgs_full (mail_op, 
3043                                                                      data,
3044                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3045                                                                      helper,
3046                                                                      paste_as_attachment_free);
3047                         }
3048                 }
3049         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3050                 ModestEmailClipboard *clipboard = NULL;
3051                 TnyFolder *src_folder = NULL;
3052                 TnyFolderStore *folder_store = NULL;
3053                 TnyList *data = NULL;           
3054                 gboolean delete = FALSE;
3055                 
3056                 /* Check clipboard source */
3057                 clipboard = modest_runtime_get_email_clipboard ();
3058                 if (modest_email_clipboard_cleared (clipboard)) 
3059                         return;
3060                 
3061                 /* Get elements to paste */
3062                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3063
3064                 /* Create a new mail operation */
3065                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3066                 
3067                 /* Get destination folder */
3068                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3069
3070                 /* transfer messages  */
3071                 if (data != NULL) {
3072                         gint response = 0;
3073
3074                         /* Ask for user confirmation */
3075                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3076                                                               TNY_FOLDER (folder_store), 
3077                                                               delete,
3078                                                               data);
3079                         
3080                         if (response == GTK_RESPONSE_OK) {
3081                                 /* Launch notification */
3082                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3083                                                                              _CS("ckct_nw_pasting"));
3084                                 if (inf_note != NULL)  {
3085                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3086                                         gtk_widget_show (GTK_WIDGET(inf_note));
3087                                 }
3088
3089                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3090                                 modest_mail_operation_xfer_msgs (mail_op, 
3091                                                                  data,
3092                                                                  TNY_FOLDER (folder_store),
3093                                                                  delete,
3094                                                                  paste_msgs_cb,
3095                                                                  inf_note);                             
3096                         } else {
3097                                 g_object_unref (mail_op);
3098                         }
3099                         
3100                 } else if (src_folder != NULL) {                        
3101                         /* Launch notification */
3102                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3103                                                                      _CS("ckct_nw_pasting"));
3104                         if (inf_note != NULL)  {
3105                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3106                                 gtk_widget_show (GTK_WIDGET(inf_note));
3107                         }
3108                         
3109                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3110                         modest_mail_operation_xfer_folder (mail_op, 
3111                                                            src_folder,
3112                                                            folder_store,
3113                                                            delete,
3114                                                            paste_msgs_cb,
3115                                                            inf_note);
3116                 }
3117
3118                 /* Free */
3119                 if (data != NULL) 
3120                         g_object_unref (data);
3121                 if (src_folder != NULL) 
3122                         g_object_unref (src_folder);
3123                 if (folder_store != NULL) 
3124                         g_object_unref (folder_store);
3125         }
3126 }
3127
3128
3129 void
3130 modest_ui_actions_on_select_all (GtkAction *action,
3131                                  ModestWindow *window)
3132 {
3133         GtkWidget *focused_widget;
3134
3135         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3136         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3137                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3138         } else if (GTK_IS_LABEL (focused_widget)) {
3139                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3140         } else if (GTK_IS_EDITABLE (focused_widget)) {
3141                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3142         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3143                 GtkTextBuffer *buffer;
3144                 GtkTextIter start, end;
3145
3146                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3147                 gtk_text_buffer_get_start_iter (buffer, &start);
3148                 gtk_text_buffer_get_end_iter (buffer, &end);
3149                 gtk_text_buffer_select_range (buffer, &start, &end);
3150         } else if (GTK_IS_HTML (focused_widget)) {
3151                 gtk_html_select_all (GTK_HTML (focused_widget));
3152         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3153                 GtkWidget *header_view = focused_widget;
3154                 GtkTreeSelection *selection = NULL;
3155                 
3156                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3157                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3158                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3159                 }
3160                                 
3161                 /* Disable window dimming management */
3162                 modest_window_disable_dimming (MODEST_WINDOW(window));
3163                 
3164                 /* Select all messages */
3165                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3166                 gtk_tree_selection_select_all (selection);
3167
3168                 /* Set focuse on header view */
3169                 gtk_widget_grab_focus (header_view);
3170
3171
3172                 /* Enable window dimming management */
3173                 modest_window_enable_dimming (MODEST_WINDOW(window));
3174                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3175         }
3176
3177 }
3178
3179 void
3180 modest_ui_actions_on_mark_as_read (GtkAction *action,
3181                                    ModestWindow *window)
3182 {       
3183         g_return_if_fail (MODEST_IS_WINDOW(window));
3184                 
3185         /* Mark each header as read */
3186         do_headers_action (window, headers_action_mark_as_read, NULL);
3187 }
3188
3189 void
3190 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3191                                      ModestWindow *window)
3192 {       
3193         g_return_if_fail (MODEST_IS_WINDOW(window));
3194                 
3195         /* Mark each header as read */
3196         do_headers_action (window, headers_action_mark_as_unread, NULL);
3197 }
3198
3199 void
3200 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3201