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