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