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