e887e02263b39766957a9356afd34e5ae78afec8
[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, new_messages_arrived, info->win);
1708         g_object_unref (G_OBJECT (mail_op));
1709         
1710  clean:
1711         /* Frees */
1712         if (info->account_name)
1713                 g_free (info->account_name);
1714         if (info->win)
1715                 g_object_unref (info->win);
1716         if (info->account)
1717                 g_object_unref (info->account);
1718         g_slice_free (SendReceiveInfo, info);
1719 }
1720
1721 /*
1722  * This function performs the send & receive required actions. The
1723  * window is used to create the mail operation. Typically it should
1724  * always be the main window, but we pass it as argument in order to
1725  * be more flexible.
1726  */
1727 void
1728 modest_ui_actions_do_send_receive (const gchar *account_name, 
1729                                    ModestWindow *win)
1730 {
1731         gchar *acc_name = NULL;
1732         SendReceiveInfo *info;
1733         ModestTnyAccountStore *acc_store;
1734
1735         /* If no account name was provided then get the current account, and if
1736            there is no current account then pick the default one: */
1737         if (!account_name) {
1738                 if (win)
1739                         acc_name = g_strdup (modest_window_get_active_account (win));
1740                 if (!acc_name)
1741                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1742                 if (!acc_name) {
1743                         g_printerr ("modest: cannot get default account\n");
1744                         return;
1745                 }
1746         } else {
1747                 acc_name = g_strdup (account_name);
1748         }
1749
1750         acc_store = modest_runtime_get_account_store ();
1751
1752         /* Create the info for the connect and perform */
1753         info = g_slice_new (SendReceiveInfo);
1754         info->account_name = acc_name;
1755         info->win = (win) ? g_object_ref (win) : NULL;
1756         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1757                                                                      TNY_ACCOUNT_TYPE_STORE);
1758
1759         /* Invoke the connect and perform */
1760         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, info->account, 
1761                                              do_send_receive_performer, info);
1762 }
1763
1764
1765 static void
1766 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1767                                   ModestWindow *win)
1768 {
1769         TnyTransportAccount *transport_account;
1770         TnySendQueue *send_queue = NULL;
1771         GError *error = NULL;
1772
1773         /* Get transport account */
1774         transport_account =
1775                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1776                                       (modest_runtime_get_account_store(),
1777                                        account_name,
1778                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1779         if (!transport_account) {
1780                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1781                 goto frees;
1782         }
1783
1784         /* Get send queue*/
1785         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1786         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1787                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1788                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1789                              "modest: could not find send queue for account\n");
1790         } else {
1791                 /* Keeep messages in outbox folder */
1792                 tny_send_queue_cancel (send_queue, FALSE, &error);
1793         }       
1794
1795  frees:
1796         if (transport_account != NULL) 
1797                 g_object_unref (G_OBJECT (transport_account));
1798 }
1799
1800 static void
1801 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1802 {
1803         GSList *account_names, *iter;
1804
1805         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1806                                                           TRUE);
1807
1808         iter = account_names;
1809         while (iter) {                  
1810                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1811                 iter = g_slist_next (iter);
1812         }
1813
1814         modest_account_mgr_free_account_names (account_names);
1815         account_names = NULL;
1816 }
1817
1818 void
1819 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1820
1821 {
1822         /* Check if accounts exist */
1823         gboolean accounts_exist = 
1824                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1825         
1826         /* If not, allow the user to create an account before trying to send/receive. */
1827         if (!accounts_exist)
1828                 modest_ui_actions_on_accounts (NULL, win);
1829         
1830         /* Cancel all sending operaitons */     
1831         modest_ui_actions_cancel_send_all (win);
1832 }
1833
1834 /*
1835  * Refreshes all accounts. This function will be used by automatic
1836  * updates
1837  */
1838 void
1839 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1840 {
1841         GSList *account_names, *iter;
1842
1843         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1844                                                           TRUE);
1845
1846         iter = account_names;
1847         while (iter) {                  
1848                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1849                 iter = g_slist_next (iter);
1850         }
1851
1852         modest_account_mgr_free_account_names (account_names);
1853         account_names = NULL;
1854 }
1855
1856 /*
1857  * Handler of the click on Send&Receive button in the main toolbar
1858  */
1859 void
1860 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1861 {
1862         /* Check if accounts exist */
1863         gboolean accounts_exist = 
1864                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1865         
1866         /* If not, allow the user to create an account before trying to send/receive. */
1867         if (!accounts_exist)
1868                 modest_ui_actions_on_accounts (NULL, win);
1869         
1870         /* Refresh the active account */
1871         modest_ui_actions_do_send_receive (NULL, win);
1872 }
1873
1874
1875 void
1876 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1877 {
1878         ModestConf *conf;
1879         GtkWidget *header_view;
1880         
1881         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1882
1883         header_view = modest_main_window_get_child_widget (main_window,
1884                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1885         if (!header_view)
1886                 return;
1887
1888         conf = modest_runtime_get_conf ();
1889         
1890         /* what is saved/restored is depending on the style; thus; we save with
1891          * old style, then update the style, and restore for this new style
1892          */
1893         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1894         
1895         if (modest_header_view_get_style
1896             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1897                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1898                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1899         else
1900                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1901                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1902
1903         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1904                                       MODEST_CONF_HEADER_VIEW_KEY);
1905 }
1906
1907
1908 void 
1909 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1910                                       TnyHeader *header,
1911                                       ModestMainWindow *main_window)
1912 {
1913         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1914         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1915         
1916         /* in the case the folder is empty, show the empty folder message and focus
1917          * folder view */
1918         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1919                 if (modest_header_view_is_empty (header_view)) {
1920                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1921                         GtkWidget *folder_view = 
1922                                 modest_main_window_get_child_widget (main_window,
1923                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1924                         if (folder != NULL) 
1925                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1926                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1927                         return;
1928                 }
1929         }
1930         /* If no header has been selected then exit */
1931         if (!header)
1932                 return;
1933
1934         /* Update focus */
1935         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1936             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1937
1938         /* Update toolbar dimming state */
1939         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1940 }
1941
1942 void
1943 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1944                                        TnyHeader *header,
1945                                        ModestMainWindow *main_window)
1946 {
1947         TnyList *headers;
1948
1949         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1950         
1951         if (!header)
1952                 return;
1953
1954         if (modest_header_view_count_selected_headers (header_view) > 1) {
1955                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1956                 return;
1957         }
1958
1959
1960 /*      headers = tny_simple_list_new (); */
1961 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1962         headers = modest_header_view_get_selected_headers (header_view);
1963
1964         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
1965
1966         g_object_unref (headers);
1967 }
1968
1969 static void
1970 set_active_account_from_tny_account (TnyAccount *account,
1971                                      ModestWindow *window)
1972 {
1973         const gchar *server_acc_name = tny_account_get_id (account);
1974         
1975         /* We need the TnyAccount provided by the
1976            account store because that is the one that
1977            knows the name of the Modest account */
1978         TnyAccount *modest_server_account = modest_server_account = 
1979                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1980                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1981                                                              server_acc_name);
1982         if (!modest_server_account) {
1983                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1984                 return;
1985         }
1986
1987         /* Update active account, but only if it's not a pseudo-account */
1988         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1989             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1990                 const gchar *modest_acc_name = 
1991                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1992                 if (modest_acc_name)
1993                         modest_window_set_active_account (window, modest_acc_name);
1994         }
1995         
1996         g_object_unref (modest_server_account);
1997 }
1998
1999
2000 static void
2001 folder_refreshed_cb (ModestMailOperation *mail_op, 
2002                      TnyFolder *folder, 
2003                      gpointer user_data)
2004 {
2005         ModestMainWindow *win = NULL;
2006         GtkWidget *header_view;
2007         gboolean folder_empty = FALSE;
2008         gboolean all_marked_as_deleted = FALSE;
2009
2010         g_return_if_fail (TNY_IS_FOLDER (folder));
2011
2012         win = MODEST_MAIN_WINDOW (user_data);
2013         header_view = 
2014                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2015
2016         if (header_view) {
2017                 TnyFolder *current_folder;
2018
2019                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2020                 if (current_folder != NULL && folder != current_folder) {
2021                         g_object_unref (current_folder);
2022                         return;
2023                 }
2024                 g_object_unref (current_folder);
2025         }
2026
2027         /* Check if folder is empty and set headers view contents style */
2028         folder_empty = (tny_folder_get_all_count (folder) == 0);
2029         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
2030         if (folder_empty || all_marked_as_deleted)
2031                 modest_main_window_set_contents_style (win,
2032                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2033 }
2034
2035 void 
2036 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2037                                                TnyFolderStore *folder_store, 
2038                                                gboolean selected,
2039                                                ModestMainWindow *main_window)
2040 {
2041         ModestConf *conf;
2042         GtkWidget *header_view;
2043
2044         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2045
2046         header_view = modest_main_window_get_child_widget(main_window,
2047                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2048         if (!header_view)
2049                 return;
2050         
2051         conf = modest_runtime_get_conf ();
2052
2053         if (TNY_IS_ACCOUNT (folder_store)) {
2054                 if (selected) {
2055                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2056                         
2057                         /* Show account details */
2058                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2059                 }
2060         } else {
2061                 if (TNY_IS_FOLDER (folder_store) && selected) {
2062                         
2063                         /* Update the active account */
2064                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2065                         if (account) {
2066                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2067                                 g_object_unref (account);
2068                                 account = NULL;
2069                         }
2070
2071                         /* Set the header style by default, it could
2072                            be changed later by the refresh callback to
2073                            empty */
2074                         modest_main_window_set_contents_style (main_window, 
2075                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2076
2077                         /* Set folder on header view. This function
2078                            will call tny_folder_refresh_async so we
2079                            pass a callback that will be called when
2080                            finished. We use that callback to set the
2081                            empty view if there are no messages */
2082                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2083                                                        TNY_FOLDER (folder_store),
2084                                                        folder_refreshed_cb,
2085                                                        main_window);
2086                         
2087                         /* Restore configuration. We need to do this
2088                            *after* the set_folder because the widget
2089                            memory asks the header view about its
2090                            folder  */
2091                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2092                                                       G_OBJECT(header_view),
2093                                                       MODEST_CONF_HEADER_VIEW_KEY);
2094                 } else {
2095                         /* Update the active account */
2096                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2097                         /* Save only if we're seeing headers */
2098                         if (modest_main_window_get_contents_style (main_window) ==
2099                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2100                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2101                                                            MODEST_CONF_HEADER_VIEW_KEY);
2102                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2103                 }
2104         }
2105
2106         /* Update toolbar dimming state */
2107         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2108 }
2109
2110 void 
2111 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2112                                      ModestWindow *win)
2113 {
2114         GtkWidget *dialog;
2115         gchar *txt, *item;
2116         gboolean online;
2117
2118         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2119         
2120         online = tny_device_is_online (modest_runtime_get_device());
2121
2122         if (online) {
2123                 /* already online -- the item is simply not there... */
2124                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2125                                                  GTK_DIALOG_MODAL,
2126                                                  GTK_MESSAGE_WARNING,
2127                                                  GTK_BUTTONS_NONE,
2128                                                  _("The %s you selected cannot be found"),
2129                                                  item);
2130                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2131                 gtk_dialog_run (GTK_DIALOG(dialog));
2132         } else {
2133                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2134                                                       GTK_WINDOW (win),
2135                                                       GTK_DIALOG_MODAL,
2136                                                       _("mcen_bd_dialog_cancel"),
2137                                                       GTK_RESPONSE_REJECT,
2138                                                       _("mcen_bd_dialog_ok"),
2139                                                       GTK_RESPONSE_ACCEPT,
2140                                                       NULL);
2141                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2142                                          "Do you want to get online?"), item);
2143                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2144                                     gtk_label_new (txt), FALSE, FALSE, 0);
2145                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2146                 g_free (txt);
2147
2148                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2149                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2150                         /* TODO: Comment about why is this commented out: */
2151                         /* modest_platform_connect_and_wait (); */
2152                 }
2153         }
2154         gtk_widget_destroy (dialog);
2155 }
2156
2157 void
2158 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2159                                      ModestWindow *win)
2160 {
2161         /* g_message ("%s %s", __FUNCTION__, link); */
2162 }       
2163
2164
2165 void
2166 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2167                                         ModestWindow *win)
2168 {
2169         modest_platform_activate_uri (link);
2170 }
2171
2172 void
2173 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2174                                           ModestWindow *win)
2175 {
2176         modest_platform_show_uri_popup (link);
2177 }
2178
2179 void
2180 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2181                                              ModestWindow *win)
2182 {
2183         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2184 }
2185
2186 void
2187 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2188                                           const gchar *address,
2189                                           ModestWindow *win)
2190 {
2191         /* g_message ("%s %s", __FUNCTION__, address); */
2192 }
2193
2194 static void
2195 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2196                       TnyMsg *saved_draft,
2197                       gpointer user_data)
2198 {
2199         ModestMsgEditWindow *edit_window;
2200         ModestMainWindow *win;
2201
2202         /* FIXME. Make the header view sensitive again. This is a
2203          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2204          * for details */
2205         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2206                                          modest_runtime_get_window_mgr(), FALSE));
2207         if (win != NULL) {
2208                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2209                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2210                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2211         }
2212
2213         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2214
2215         /* If there was any error do nothing */
2216         if (modest_mail_operation_get_error (mail_op) != NULL)
2217                 return;
2218
2219         modest_msg_edit_window_set_draft (edit_window, saved_draft);
2220 }
2221
2222 void
2223 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2224 {
2225         TnyTransportAccount *transport_account;
2226         ModestMailOperation *mail_operation;
2227         MsgData *data;
2228         gchar *account_name, *from;
2229         ModestAccountMgr *account_mgr;
2230         char *info_text;
2231
2232         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2233         
2234         data = modest_msg_edit_window_get_msg_data (edit_window);
2235
2236         account_name = g_strdup (data->account_name);
2237         account_mgr = modest_runtime_get_account_mgr();
2238         if (!account_name)
2239                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2240         if (!account_name) 
2241                 account_name = modest_account_mgr_get_default_account (account_mgr);
2242         if (!account_name) {
2243                 g_printerr ("modest: no account found\n");
2244                 modest_msg_edit_window_free_msg_data (edit_window, data);
2245                 return;
2246         }
2247
2248         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2249                 account_name = g_strdup (data->account_name);
2250         }
2251
2252         transport_account =
2253                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2254                                       (modest_runtime_get_account_store(),
2255                                        account_name,
2256                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2257         if (!transport_account) {
2258                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2259                 g_free (account_name);
2260                 modest_msg_edit_window_free_msg_data (edit_window, data);
2261                 return;
2262         }
2263         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2264
2265         /* Create the mail operation */         
2266         mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2267         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2268
2269         modest_mail_operation_save_to_drafts (mail_operation,
2270                                               transport_account,
2271                                               data->draft_msg,
2272                                               from,
2273                                               data->to, 
2274                                               data->cc, 
2275                                               data->bcc,
2276                                               data->subject, 
2277                                               data->plain_body, 
2278                                               data->html_body,
2279                                               data->attachments,
2280                                               data->images,
2281                                               data->priority_flags,
2282                                               on_save_to_drafts_cb,
2283                                               edit_window);
2284         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2285         modest_platform_information_banner (NULL, NULL, info_text);
2286
2287         /* Frees */
2288         g_free (info_text);
2289         g_free (from);
2290         g_free (account_name);
2291         g_object_unref (G_OBJECT (transport_account));
2292         g_object_unref (G_OBJECT (mail_operation));
2293
2294         modest_msg_edit_window_free_msg_data (edit_window, data);
2295         modest_msg_edit_window_reset_modified (edit_window);
2296
2297         /* ** FIXME **
2298          * If the drafts folder is selected then make the header view
2299          * insensitive while the message is being saved to drafts
2300          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2301          * is not very clean but it avoids letting the drafts folder
2302          * in an inconsistent state: the user could edit the message
2303          * being saved and undesirable things would happen.
2304          * In the average case the user won't notice anything at
2305          * all. In the worst case (the user is editing a really big
2306          * file from Drafts) the header view will be insensitive
2307          * during the saving process (10 or 20 seconds, depending on
2308          * the message). Anyway this is just a quick workaround: once
2309          * we find a better solution it should be removed
2310          * See NB#65125 (commend #18) for details.
2311          */
2312         ModestMainWindow *win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2313                 modest_runtime_get_window_mgr(), FALSE));
2314         if (win != NULL) {
2315                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2316                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2317                 if (view != NULL) {
2318                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2319                         if (folder) {
2320                                 if (modest_tny_folder_is_local_folder(folder)) {
2321                                         TnyFolderType folder_type;
2322                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2323                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2324                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2325                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2326                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2327                                         }
2328                                 }
2329                         }
2330                         if (folder != NULL) g_object_unref(folder);
2331                 }
2332         }
2333 }
2334
2335 /* For instance, when clicking the Send toolbar button when editing a message: */
2336 void
2337 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2338 {
2339         TnyTransportAccount *transport_account = NULL;
2340
2341         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2342
2343         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2344                 return;
2345         
2346         /* FIXME: Code added just for testing. The final version will
2347            use the send queue provided by tinymail and some
2348            classifier */
2349         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2350
2351         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2352         gchar *account_name = g_strdup (data->account_name);
2353         if (!account_name)
2354                 g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2355
2356         if (!account_name) 
2357                 account_name = modest_account_mgr_get_default_account (account_mgr);
2358                 
2359         if (!account_name) {
2360                 modest_msg_edit_window_free_msg_data (edit_window, data);
2361                 /* Run account setup wizard */
2362                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window)))
2363                         return;
2364         }
2365         
2366         /* Get the currently-active transport account for this modest account: */
2367 /*      TnyTransportAccount *transport_account = */
2368 /*              TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection */
2369 /*                                    (modest_runtime_get_account_store(), */
2370 /*                                     account_name)); */
2371         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2372                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2373                                                           (modest_runtime_get_account_store(),
2374                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2375         }
2376         
2377         if (!transport_account) {
2378                 /* Run account setup wizard */
2379                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2380                         return;
2381         }
2382         
2383         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2384
2385         /* Create the mail operation */
2386         ModestMailOperation *mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2387         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2388
2389         modest_mail_operation_send_new_mail (mail_operation,
2390                                              transport_account,
2391                                              data->draft_msg,
2392                                              from,
2393                                              data->to, 
2394                                              data->cc, 
2395                                              data->bcc,
2396                                              data->subject, 
2397                                              data->plain_body, 
2398                                              data->html_body,
2399                                              data->attachments,
2400                                              data->images,
2401                                              data->priority_flags);
2402
2403         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2404                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2405
2406                                              
2407         /* Free data: */
2408         g_free (from);
2409         g_free (account_name);
2410         g_object_unref (G_OBJECT (transport_account));
2411         g_object_unref (G_OBJECT (mail_operation));
2412
2413         modest_msg_edit_window_free_msg_data (edit_window, data);
2414         modest_msg_edit_window_set_sent (edit_window, TRUE);
2415
2416         /* Save settings and close the window: */
2417         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2418 }
2419
2420 void 
2421 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2422                                   ModestMsgEditWindow *window)
2423 {
2424         ModestMsgEditFormatState *format_state = NULL;
2425
2426         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2427         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2428
2429         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2430                 return;
2431
2432         format_state = modest_msg_edit_window_get_format_state (window);
2433         g_return_if_fail (format_state != NULL);
2434
2435         format_state->bold = gtk_toggle_action_get_active (action);
2436         modest_msg_edit_window_set_format_state (window, format_state);
2437         g_free (format_state);
2438         
2439 }
2440
2441 void 
2442 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2443                                      ModestMsgEditWindow *window)
2444 {
2445         ModestMsgEditFormatState *format_state = NULL;
2446
2447         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2448         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2449
2450         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2451                 return;
2452
2453         format_state = modest_msg_edit_window_get_format_state (window);
2454         g_return_if_fail (format_state != NULL);
2455
2456         format_state->italics = gtk_toggle_action_get_active (action);
2457         modest_msg_edit_window_set_format_state (window, format_state);
2458         g_free (format_state);
2459         
2460 }
2461
2462 void 
2463 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2464                                      ModestMsgEditWindow *window)
2465 {
2466         ModestMsgEditFormatState *format_state = NULL;
2467
2468         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2469         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2470
2471         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2472                 return;
2473
2474         format_state = modest_msg_edit_window_get_format_state (window);
2475         g_return_if_fail (format_state != NULL);
2476
2477         format_state->bullet = gtk_toggle_action_get_active (action);
2478         modest_msg_edit_window_set_format_state (window, format_state);
2479         g_free (format_state);
2480         
2481 }
2482
2483 void 
2484 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2485                                      GtkRadioAction *selected,
2486                                      ModestMsgEditWindow *window)
2487 {
2488         ModestMsgEditFormatState *format_state = NULL;
2489         GtkJustification value;
2490
2491         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2492
2493         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2494                 return;
2495
2496         value = gtk_radio_action_get_current_value (selected);
2497
2498         format_state = modest_msg_edit_window_get_format_state (window);
2499         g_return_if_fail (format_state != NULL);
2500
2501         format_state->justification = value;
2502         modest_msg_edit_window_set_format_state (window, format_state);
2503         g_free (format_state);
2504 }
2505
2506 void 
2507 modest_ui_actions_on_select_editor_color (GtkAction *action,
2508                                           ModestMsgEditWindow *window)
2509 {
2510         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2511         g_return_if_fail (GTK_IS_ACTION (action));
2512
2513         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2514                 return;
2515
2516         modest_msg_edit_window_select_color (window);
2517 }
2518
2519 void 
2520 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2521                                                      ModestMsgEditWindow *window)
2522 {
2523         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2524         g_return_if_fail (GTK_IS_ACTION (action));
2525
2526         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2527                 return;
2528
2529         modest_msg_edit_window_select_background_color (window);
2530 }
2531
2532 void 
2533 modest_ui_actions_on_insert_image (GtkAction *action,
2534                                    ModestMsgEditWindow *window)
2535 {
2536         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2537         g_return_if_fail (GTK_IS_ACTION (action));
2538
2539         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2540                 return;
2541
2542         modest_msg_edit_window_insert_image (window);
2543 }
2544
2545 void 
2546 modest_ui_actions_on_attach_file (GtkAction *action,
2547                                   ModestMsgEditWindow *window)
2548 {
2549         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2550         g_return_if_fail (GTK_IS_ACTION (action));
2551
2552         modest_msg_edit_window_offer_attach_file (window);
2553 }
2554
2555 void 
2556 modest_ui_actions_on_remove_attachments (GtkAction *action,
2557                                          ModestMsgEditWindow *window)
2558 {
2559         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2560         g_return_if_fail (GTK_IS_ACTION (action));
2561
2562         modest_msg_edit_window_remove_attachments (window, NULL);
2563 }
2564
2565 static void
2566 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2567                                             gpointer user_data)
2568 {
2569         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2570         const GError *error = modest_mail_operation_get_error (mail_op);
2571
2572         if(error) {
2573                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2574                                                     _("mail_in_ui_folder_create_error"));
2575         }
2576 }
2577
2578 static void
2579 modest_ui_actions_create_folder(GtkWidget *parent_window,
2580                                 GtkWidget *folder_view)
2581 {
2582         TnyFolderStore *parent_folder;
2583
2584         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2585         
2586         if (parent_folder) {
2587                 gboolean finished = FALSE;
2588                 gint result;
2589                 gchar *folder_name = NULL, *suggested_name = NULL;
2590                 const gchar *proto_str = NULL;
2591                 TnyAccount *account;
2592
2593                 if (TNY_IS_ACCOUNT (parent_folder))
2594                         account = g_object_ref (parent_folder);
2595                 else
2596                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2597                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2598
2599                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2600                     MODEST_PROTOCOL_STORE_POP) {
2601                         finished = TRUE;
2602                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2603                 }
2604                 g_object_unref (account);
2605
2606                 /* Run the new folder dialog */
2607                 while (!finished) {
2608                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2609                                                                         parent_folder,
2610                                                                         suggested_name,
2611                                                                         &folder_name);
2612
2613                         g_free (suggested_name);
2614                         suggested_name = NULL;
2615
2616                         if (result == GTK_RESPONSE_ACCEPT) {
2617                                 ModestMailOperation *mail_op;
2618                                 TnyFolder *new_folder = NULL;
2619
2620                                 mail_op  = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2621                                                                                           modest_ui_actions_new_folder_error_handler,
2622                                                                                           parent_window, NULL);
2623
2624                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2625                                                                  mail_op);
2626                                 new_folder = modest_mail_operation_create_folder (mail_op,
2627                                                                                   parent_folder,
2628                                                                                   (const gchar *) folder_name);
2629                                 if (new_folder) {
2630                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2631                                                                           new_folder, TRUE);
2632
2633                                         g_object_unref (new_folder);
2634                                         finished = TRUE;
2635                                 }
2636                                 g_object_unref (mail_op);
2637                         } else {
2638                                 finished = TRUE;
2639                         }
2640
2641                         suggested_name = folder_name;
2642                         folder_name = NULL;
2643                 }
2644
2645                 g_object_unref (parent_folder);
2646         }
2647 }
2648
2649 void 
2650 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2651 {
2652         GtkWidget *folder_view;
2653         
2654         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2655
2656         folder_view = modest_main_window_get_child_widget (main_window,
2657                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2658         if (!folder_view)
2659                 return;
2660
2661         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2662 }
2663
2664 static void
2665 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2666                                                gpointer user_data)
2667 {
2668         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2669         const GError *error = NULL;
2670         const gchar *message = NULL;
2671         
2672         /* Get error message */
2673         error = modest_mail_operation_get_error (mail_op);
2674         if (!error)
2675                 g_return_if_reached ();
2676
2677         switch (error->code) {
2678         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2679                 message = _CS("ckdg_ib_folder_already_exists");
2680                 break;
2681         default:
2682                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2683                            error->code, error->message);
2684                 return;
2685         }
2686
2687         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2688 }
2689
2690 void 
2691 modest_ui_actions_on_rename_folder (GtkAction *action,
2692                                      ModestMainWindow *main_window)
2693 {
2694         TnyFolderStore *folder;
2695         GtkWidget *folder_view;
2696         GtkWidget *header_view; 
2697
2698         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2699
2700         folder_view = modest_main_window_get_child_widget (main_window,
2701                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2702         if (!folder_view)
2703                 return;
2704
2705         header_view = modest_main_window_get_child_widget (main_window,
2706                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2707         
2708         if (!header_view)
2709                 return;
2710
2711         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2712
2713         if (!folder)
2714                 return;
2715
2716         if (TNY_IS_FOLDER (folder)) {
2717                 gchar *folder_name;
2718                 gint response;
2719                 const gchar *current_name;
2720                 TnyFolderStore *parent;
2721                 gboolean do_rename = TRUE;
2722
2723                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2724                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2725                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2726                                                                      parent, current_name, 
2727                                                                      &folder_name);
2728                 g_object_unref (parent);
2729
2730                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2731                         do_rename = FALSE;
2732                 } else if (modest_platform_is_network_folderstore(folder) &&
2733                            !tny_device_is_online (modest_runtime_get_device())) {
2734                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2735                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2736                         g_object_unref(account);
2737                 }
2738
2739                 if (do_rename) {
2740                         ModestMailOperation *mail_op;
2741                         GtkTreeSelection *sel = NULL;
2742
2743                         mail_op = 
2744                                 modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2745                                                                                modest_ui_actions_rename_folder_error_handler,
2746                                                                                main_window, NULL);
2747
2748                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2749                                                          mail_op);
2750
2751                         /* Clear the headers view */
2752                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2753                         gtk_tree_selection_unselect_all (sel);
2754
2755                         /* Select *after* the changes */
2756                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2757                                                           TNY_FOLDER(folder), TRUE);
2758
2759                         /* Actually rename the folder */
2760                         modest_mail_operation_rename_folder (mail_op,
2761                                                              TNY_FOLDER (folder),
2762                                                              (const gchar *) folder_name);
2763
2764                         g_object_unref (mail_op);
2765                         g_free (folder_name);
2766                 }
2767         }
2768         g_object_unref (folder);
2769 }
2770
2771 static void
2772 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2773                                                gpointer user_data)
2774 {
2775         GObject *win = modest_mail_operation_get_source (mail_op);
2776
2777         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2778                                                 _("mail_in_ui_folder_delete_error"));
2779         g_object_unref (win);
2780 }
2781
2782 static gboolean
2783 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2784 {
2785         TnyFolderStore *folder;
2786         GtkWidget *folder_view;
2787         gint response;
2788         gchar *message;
2789         gboolean do_delete = TRUE;
2790
2791         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2792
2793         folder_view = modest_main_window_get_child_widget (main_window,
2794                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2795         if (!folder_view)
2796                 return FALSE;
2797
2798         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2799
2800         /* Show an error if it's an account */
2801         if (!TNY_IS_FOLDER (folder)) {
2802                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2803                                                         _("mail_in_ui_folder_delete_error"));
2804                 g_object_unref (G_OBJECT (folder));
2805                 return FALSE;
2806         }
2807
2808         /* Ask the user */      
2809         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2810                                     tny_folder_get_name (TNY_FOLDER (folder)));
2811         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2812                                                             (const gchar *) message);
2813         g_free (message);
2814
2815         if (response != GTK_RESPONSE_OK) {
2816                 do_delete = FALSE;
2817         } else if (modest_platform_is_network_folderstore(folder) &&
2818                    !tny_device_is_online (modest_runtime_get_device())) {
2819                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2820                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2821                 g_object_unref(account);
2822         }
2823
2824         if (do_delete) {
2825                 ModestMailOperation *mail_op;
2826                 GtkTreeSelection *sel;
2827
2828                 /* Unselect the folder before deleting it to free the headers */
2829                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2830                 gtk_tree_selection_unselect_all (sel);
2831
2832                 /* Create the mail operation */
2833                 mail_op =
2834                         modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2835                                                                        modest_ui_actions_delete_folder_error_handler,
2836                                                                        NULL, NULL);
2837
2838                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2839                                                  mail_op);
2840                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2841                 g_object_unref (G_OBJECT (mail_op));
2842         }
2843
2844         g_object_unref (G_OBJECT (folder));
2845
2846         return do_delete;
2847 }
2848
2849 void 
2850 modest_ui_actions_on_delete_folder (GtkAction *action,
2851                                      ModestMainWindow *main_window)
2852 {
2853         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2854
2855         if (delete_folder (main_window, FALSE)) {
2856                 GtkWidget *folder_view;
2857
2858                 folder_view = modest_main_window_get_child_widget (main_window,
2859                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2860                 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2861         }
2862 }
2863
2864 void 
2865 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2866 {
2867         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2868         
2869         delete_folder (main_window, TRUE);
2870 }
2871
2872
2873 static void
2874 show_error (GtkWidget *parent_widget, const gchar* text)
2875 {
2876         hildon_banner_show_information(parent_widget, NULL, text);
2877         
2878 #if 0
2879         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2880         /*
2881           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2882           (GtkDialogFlags)0,
2883           GTK_MESSAGE_ERROR,
2884           GTK_BUTTONS_OK,
2885           text ));
2886         */
2887                  
2888         gtk_dialog_run (dialog);
2889         gtk_widget_destroy (GTK_WIDGET (dialog));
2890 #endif
2891 }
2892
2893 void
2894 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2895                                          const gchar* server_account_name,
2896                                          gchar **username,
2897                                          gchar **password, 
2898                                          gboolean *cancel, 
2899                                          gboolean *remember,
2900                                          ModestMainWindow *main_window)
2901 {
2902         g_return_if_fail(server_account_name);
2903         
2904         /* Initalize output parameters: */
2905         if (cancel)
2906                 *cancel = FALSE;
2907                 
2908         if (remember)
2909                 *remember = TRUE;
2910                 
2911 #ifdef MODEST_PLATFORM_MAEMO
2912         /* Maemo uses a different (awkward) button order,
2913          * It should probably just use gtk_alternative_dialog_button_order ().
2914          */
2915         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2916                                               NULL,
2917                                               GTK_DIALOG_MODAL,
2918                                               _("mcen_bd_dialog_ok"),
2919                                               GTK_RESPONSE_ACCEPT,
2920                                               _("mcen_bd_dialog_cancel"),
2921                                               GTK_RESPONSE_REJECT,
2922                                               NULL);
2923 #else
2924         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2925                                               NULL,
2926                                               GTK_DIALOG_MODAL,
2927                                               GTK_STOCK_CANCEL,
2928                                               GTK_RESPONSE_REJECT,
2929                                               GTK_STOCK_OK,
2930                                               GTK_RESPONSE_ACCEPT,
2931                                               NULL);
2932 #endif /* MODEST_PLATFORM_MAEMO */
2933
2934         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2935         
2936         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2937                 modest_runtime_get_account_mgr(), server_account_name);
2938         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2939                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2940                 if (cancel)
2941                         *cancel = TRUE;
2942                 return;
2943         }
2944         
2945         /* This causes a warning because the logical ID has no %s in it, 
2946          * though the translation does, but there is not much we can do about that: */
2947         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2948         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2949                             FALSE, FALSE, 0);
2950         g_free (txt);
2951         g_free (server_name);
2952         server_name = NULL;
2953
2954         /* username: */
2955         gchar *initial_username = modest_account_mgr_get_server_account_username (
2956                 modest_runtime_get_account_mgr(), server_account_name);
2957         
2958         GtkWidget *entry_username = gtk_entry_new ();
2959         if (initial_username)
2960                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2961         /* Dim this if a connection has ever succeeded with this username,
2962          * as per the UI spec: */
2963         const gboolean username_known = 
2964                 modest_account_mgr_get_server_account_username_has_succeeded(
2965                         modest_runtime_get_account_mgr(), server_account_name);
2966         gtk_widget_set_sensitive (entry_username, !username_known);
2967         
2968 #ifdef MODEST_PLATFORM_MAEMO
2969         /* Auto-capitalization is the default, so let's turn it off: */
2970         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2971         
2972         /* Create a size group to be used by all captions.
2973          * Note that HildonCaption does not create a default size group if we do not specify one.
2974          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2975         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2976         
2977         GtkWidget *caption = hildon_caption_new (sizegroup, 
2978                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2979         gtk_widget_show (entry_username);
2980         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2981                 FALSE, FALSE, MODEST_MARGIN_HALF);
2982         gtk_widget_show (caption);
2983 #else 
2984         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2985                             TRUE, FALSE, 0);
2986 #endif /* MODEST_PLATFORM_MAEMO */      
2987                             
2988         /* password: */
2989         GtkWidget *entry_password = gtk_entry_new ();
2990         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2991         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2992         
2993 #ifdef MODEST_PLATFORM_MAEMO
2994         /* Auto-capitalization is the default, so let's turn it off: */
2995         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2996                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2997         
2998         caption = hildon_caption_new (sizegroup, 
2999                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3000         gtk_widget_show (entry_password);
3001         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3002                 FALSE, FALSE, MODEST_MARGIN_HALF);
3003         gtk_widget_show (caption);
3004         g_object_unref (sizegroup);
3005 #else 
3006         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3007                             TRUE, FALSE, 0);
3008 #endif /* MODEST_PLATFORM_MAEMO */      
3009
3010         if (initial_username != NULL)
3011                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3012                                 
3013 /* This is not in the Maemo UI spec:
3014         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3015         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3016                             TRUE, FALSE, 0);
3017 */
3018
3019         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3020         
3021         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3022                 if (username) {
3023                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3024                         
3025                         modest_account_mgr_set_server_account_username (
3026                                  modest_runtime_get_account_mgr(), server_account_name, 
3027                                  *username);
3028                                  
3029                         const gboolean username_was_changed = 
3030                                 (strcmp (*username, initial_username) != 0);
3031                         if (username_was_changed) {
3032                                 g_warning ("%s: tinymail does not yet support changing the "
3033                                         "username in the get_password() callback.\n", __FUNCTION__);
3034                         }
3035                 }
3036                         
3037                 if (password) {
3038                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3039                         
3040                         /* We do not save the password in the configuration, 
3041                          * because this function is only called for passwords that should 
3042                          * not be remembered:
3043                         modest_server_account_set_password (
3044                                  modest_runtime_get_account_mgr(), server_account_name, 
3045                                  *password);
3046                         */
3047                 }
3048                 
3049                 if (cancel)
3050                         *cancel   = FALSE;
3051                         
3052         } else {
3053                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3054                 
3055                 if (username)
3056                         *username = NULL;
3057                         
3058                 if (password)
3059                         *password = NULL;
3060                         
3061                 if (cancel)
3062                         *cancel   = TRUE;
3063         }
3064
3065 /* This is not in the Maemo UI spec:
3066         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3067                 *remember = TRUE;
3068         else
3069                 *remember = FALSE;
3070 */
3071
3072         gtk_widget_destroy (dialog);
3073         
3074         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3075 }
3076
3077 void
3078 modest_ui_actions_on_cut (GtkAction *action,
3079                           ModestWindow *window)
3080 {
3081         GtkWidget *focused_widget;
3082         GtkClipboard *clipboard;
3083
3084         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3085         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3086         if (GTK_IS_EDITABLE (focused_widget)) {
3087                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3088                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3089                 gtk_clipboard_store (clipboard);
3090         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3091                 GtkTextBuffer *buffer;
3092
3093                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3094                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3095                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3096                 gtk_clipboard_store (clipboard);
3097         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3098                 TnyList *header_list = modest_header_view_get_selected_headers (
3099                                 MODEST_HEADER_VIEW (focused_widget));
3100                 gboolean continue_download = FALSE;
3101                 gint num_of_unc_msgs;
3102
3103                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3104
3105                 if (num_of_unc_msgs) {
3106                         TnyAccount *account = get_account_from_header_list (header_list);
3107                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3108                         g_object_unref (account);
3109                 }
3110
3111                 if (num_of_unc_msgs == 0 || continue_download) {
3112 /*                      modest_platform_information_banner (
3113                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3114                         modest_header_view_cut_selection (
3115                                         MODEST_HEADER_VIEW (focused_widget));
3116                 }
3117
3118                 g_object_unref (header_list);
3119         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3120                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3121         }
3122 }
3123
3124 void
3125 modest_ui_actions_on_copy (GtkAction *action,
3126                            ModestWindow *window)
3127 {
3128         GtkClipboard *clipboard;
3129         GtkWidget *focused_widget;
3130         gboolean copied = TRUE;
3131
3132         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3133         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3134
3135         if (GTK_IS_LABEL (focused_widget)) {
3136                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3137                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3138                 gtk_clipboard_store (clipboard);
3139         } else if (GTK_IS_EDITABLE (focused_widget)) {
3140                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3141                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3142                 gtk_clipboard_store (clipboard);
3143         } else if (GTK_IS_HTML (focused_widget)) {
3144                 gtk_html_copy (GTK_HTML (focused_widget));
3145                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3146                 gtk_clipboard_store (clipboard);
3147         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3148                 GtkTextBuffer *buffer;
3149                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3150                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3151                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3152                 gtk_clipboard_store (clipboard);
3153         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3154                 TnyList *header_list = modest_header_view_get_selected_headers (
3155                                 MODEST_HEADER_VIEW (focused_widget));
3156                 gboolean continue_download = FALSE;
3157                 gint num_of_unc_msgs;
3158
3159                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3160
3161                 if (num_of_unc_msgs) {
3162                         TnyAccount *account = get_account_from_header_list (header_list);
3163                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3164                         g_object_unref (account);
3165                 }
3166
3167                 if (num_of_unc_msgs == 0 || continue_download) {
3168                         modest_platform_information_banner (
3169                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3170                         modest_header_view_copy_selection (
3171                                         MODEST_HEADER_VIEW (focused_widget));
3172                 } else
3173                         copied = FALSE;
3174
3175                 g_object_unref (header_list);
3176
3177         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3178                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3179         }
3180
3181         /* Show information banner if there was a copy to clipboard */
3182         if(copied)
3183                 modest_platform_information_banner (
3184                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3185 }
3186
3187 void
3188 modest_ui_actions_on_undo (GtkAction *action,
3189                            ModestWindow *window)
3190 {
3191         ModestEmailClipboard *clipboard = NULL;
3192
3193         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3194                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3195         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3196                 /* Clear clipboard source */
3197                 clipboard = modest_runtime_get_email_clipboard ();
3198                 modest_email_clipboard_clear (clipboard);               
3199         }
3200         else {
3201                 g_return_if_reached ();
3202         }
3203 }
3204
3205 void
3206 modest_ui_actions_on_redo (GtkAction *action,
3207                            ModestWindow *window)
3208 {
3209         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3210                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3211         }
3212         else {
3213                 g_return_if_reached ();
3214         }
3215 }
3216
3217
3218 static void
3219 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3220 {
3221         /* destroy information note */
3222         gtk_widget_destroy (GTK_WIDGET(user_data));
3223 }
3224
3225
3226 static void
3227 paste_as_attachment_free (gpointer data)
3228 {
3229         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3230
3231         gtk_widget_destroy (helper->banner);
3232         g_object_unref (helper->banner);
3233         g_free (helper);
3234 }
3235
3236 static void
3237 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3238                             TnyHeader *header,
3239                             TnyMsg *msg,
3240                             gpointer userdata)
3241 {
3242         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3243         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3244
3245         if (msg == NULL)
3246                 return;
3247
3248         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3249         
3250 }
3251
3252 void
3253 modest_ui_actions_on_paste (GtkAction *action,
3254                             ModestWindow *window)
3255 {
3256         GtkWidget *focused_widget = NULL;
3257         GtkWidget *inf_note = NULL;
3258         ModestMailOperation *mail_op = NULL;
3259
3260         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3261         if (GTK_IS_EDITABLE (focused_widget)) {
3262                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3263         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3264                 ModestEmailClipboard *e_clipboard = NULL;
3265                 e_clipboard = modest_runtime_get_email_clipboard ();
3266                 if (modest_email_clipboard_cleared (e_clipboard)) {
3267                         GtkTextBuffer *buffer;
3268                         GtkClipboard *clipboard;
3269
3270                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3271                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3272                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3273                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3274                         ModestMailOperation *mail_op;
3275                         TnyFolder *src_folder;
3276                         TnyList *data;
3277                         gboolean delete;
3278                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3279                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3280                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3281                                                                            _CS("ckct_nw_pasting"));
3282                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3283                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3284                         if (helper->banner != NULL) {
3285                                 g_object_ref (G_OBJECT (helper->banner));
3286                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3287                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3288                         }
3289
3290                         if (data != NULL) {
3291                                 modest_mail_operation_get_msgs_full (mail_op, 
3292                                                                      data,
3293                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3294                                                                      helper,
3295                                                                      paste_as_attachment_free);
3296                         }
3297                 }
3298         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3299                 ModestEmailClipboard *clipboard = NULL;
3300                 TnyFolder *src_folder = NULL;
3301                 TnyFolderStore *folder_store = NULL;
3302                 TnyList *data = NULL;           
3303                 gboolean delete = FALSE;
3304                 
3305                 /* Check clipboard source */
3306                 clipboard = modest_runtime_get_email_clipboard ();
3307                 if (modest_email_clipboard_cleared (clipboard)) 
3308                         return;
3309                 
3310                 /* Get elements to paste */
3311                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3312
3313                 /* Create a new mail operation */
3314                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3315                 
3316                 /* Get destination folder */
3317                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3318
3319                 /* transfer messages  */
3320                 if (data != NULL) {
3321                         gint response = 0;
3322
3323                         /* Ask for user confirmation */
3324                         response = 
3325                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3326                                                                              TNY_FOLDER (folder_store), 
3327                                                                              delete,
3328                                                                              data);
3329                         
3330                         if (response == GTK_RESPONSE_OK) {
3331                                 /* Launch notification */
3332                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3333                                                                              _CS("ckct_nw_pasting"));
3334                                 if (inf_note != NULL)  {
3335                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3336                                         gtk_widget_show (GTK_WIDGET(inf_note));
3337                                 }
3338
3339                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3340                                 modest_mail_operation_xfer_msgs (mail_op, 
3341                                                                  data,
3342                                                                  TNY_FOLDER (folder_store),
3343                                                                  delete,
3344                                                                  destroy_information_note,
3345                                                                  inf_note);                             
3346                         } else {
3347                                 g_object_unref (mail_op);
3348                         }
3349                         
3350                 } else if (src_folder != NULL) {                        
3351                         /* Launch notification */
3352                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3353                                                                      _CS("ckct_nw_pasting"));
3354                         if (inf_note != NULL)  {
3355                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3356                                 gtk_widget_show (GTK_WIDGET(inf_note));
3357                         }
3358                         
3359                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3360                         modest_mail_operation_xfer_folder (mail_op, 
3361                                                            src_folder,
3362                                                            folder_store,
3363                                                            delete,
3364                                                            destroy_information_note,
3365                                                            inf_note);
3366                 }
3367
3368                 /* Free */
3369                 if (data != NULL) 
3370                         g_object_unref (data);
3371                 if (src_folder != NULL) 
3372                         g_object_unref (src_folder);
3373                 if (folder_store != NULL) 
3374                         g_object_unref (folder_store);
3375         }
3376 }
3377
3378
3379 void
3380 modest_ui_actions_on_select_all (GtkAction *action,
3381                                  ModestWindow *window)
3382 {
3383         GtkWidget *focused_widget;
3384
3385         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3386         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3387                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3388         } else if (GTK_IS_LABEL (focused_widget)) {
3389                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3390         } else if (GTK_IS_EDITABLE (focused_widget)) {
3391                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3392         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3393                 GtkTextBuffer *buffer;
3394                 GtkTextIter start, end;
3395
3396                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3397                 gtk_text_buffer_get_start_iter (buffer, &start);
3398                 gtk_text_buffer_get_end_iter (buffer, &end);
3399                 gtk_text_buffer_select_range (buffer, &start, &end);
3400         } else if (GTK_IS_HTML (focused_widget)) {
3401                 gtk_html_select_all (GTK_HTML (focused_widget));
3402         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3403                 GtkWidget *header_view = focused_widget;
3404                 GtkTreeSelection *selection = NULL;
3405                 
3406                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3407                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3408                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3409                 }
3410                                 
3411                 /* Disable window dimming management */
3412                 modest_window_disable_dimming (MODEST_WINDOW(window));
3413                 
3414                 /* Select all messages */
3415                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3416                 gtk_tree_selection_select_all (selection);
3417
3418                 /* Set focuse on header view */
3419                 gtk_widget_grab_focus (header_view);
3420
3421
3422                 /* Enable window dimming management */
3423                 modest_window_enable_dimming (MODEST_WINDOW(window));
3424                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3425         }
3426
3427 }
3428
3429 void
3430 modest_ui_actions_on_mark_as_read (GtkAction *action,
3431                                    ModestWindow *window)
3432 {       
3433         g_return_if_fail (MODEST_IS_WINDOW(window));
3434                 
3435         /* Mark each header as read */
3436         do_headers_action (window, headers_action_mark_as_read, NULL);
3437 }
3438
3439 void
3440 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3441                                      ModestWindow *window)
3442 {       
3443         g_return_if_fail (MODEST_IS_WINDOW(window));
3444                 
3445         /* Mark each header as read */
3446         do_headers_action (window, headers_action_mark_as_unread, NULL);
3447 }
3448
3449 void
3450 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3451                                   GtkRadioAction *selected,
3452                                   ModestWindow *window)
3453 {
3454         gint value;
3455
3456         value = gtk_radio_action_get_current_value (selected);
3457         if (MODEST_IS_WINDOW (window)) {
3458                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3459         }
3460 }
3461
3462 void     
3463 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3464                                                GtkRadioAction *selected,
3465                                                ModestWindow *window)
3466 {
3467         TnyHeaderFlags flags;
3468         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3469
3470         flags = gtk_radio_action_get_current_value (selected);
3471         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3472 }
3473
3474 void     
3475 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3476                                                   GtkRadioAction *selected,
3477                                                   ModestWindow *window)
3478 {
3479         gint file_format;
3480
3481         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3482
3483         file_format = gtk_radio_action_get_current_value (selected);
3484         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3485 }
3486
3487
3488 void     
3489 modest_ui_actions_on_zoom_plus (GtkAction *action,
3490                                 ModestWindow *window)
3491 {
3492         g_return_if_fail (MODEST_IS_WINDOW (window));
3493
3494         modest_window_zoom_plus (MODEST_WINDOW (window));
3495 }
3496
3497 void     
3498 modest_ui_actions_on_zoom_minus (GtkAction *action,
3499                                  ModestWindow *window)
3500 {
3501         g_return_if_fail (MODEST_IS_WINDOW (window));
3502
3503         modest_window_zoom_minus (MODEST_WINDOW (window));
3504 }
3505
3506 void     
3507 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3508                                            ModestWindow *window)
3509 {
3510         ModestWindowMgr *mgr;
3511         gboolean fullscreen, active;
3512         g_return_if_fail (MODEST_IS_WINDOW (window));
3513
3514         mgr = modest_runtime_get_window_mgr ();
3515
3516         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3517         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3518
3519         if (active != fullscreen) {
3520                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3521                 gtk_window_present (GTK_WINDOW (window));
3522         }
3523 }
3524
3525 void
3526 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3527                                         ModestWindow *window)
3528 {
3529         ModestWindowMgr *mgr;
3530         gboolean fullscreen;
3531
3532         g_return_if_fail (MODEST_IS_WINDOW (window));
3533
3534         mgr = modest_runtime_get_window_mgr ();
3535         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3536         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3537
3538         gtk_window_present (GTK_WINDOW (window));
3539 }
3540
3541 /* 
3542  * Used by modest_ui_actions_on_details to call do_headers_action 
3543  */
3544 static void
3545 headers_action_show_details (TnyHeader *header, 
3546                              ModestWindow *window,
3547                              gpointer user_data)
3548
3549 {
3550         GtkWidget *dialog;
3551         
3552         /* Create dialog */
3553         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3554
3555         /* Run dialog */
3556         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3557         gtk_widget_show_all (dialog);
3558         gtk_dialog_run (GTK_DIALOG (dialog));
3559
3560         gtk_widget_destroy (dialog);
3561 }
3562
3563 /*
3564  * Show the folder details in a ModestDetailsDialog widget
3565  */
3566 static void
3567 show_folder_details (TnyFolder *folder, 
3568                      GtkWindow *window)
3569 {
3570         GtkWidget *dialog;
3571         
3572         /* Create dialog */
3573         dialog = modest_details_dialog_new_with_folder (window, folder);
3574
3575         /* Run dialog */
3576         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3577         gtk_widget_show_all (dialog);
3578         gtk_dialog_run (GTK_DIALOG (dialog));
3579
3580         gtk_widget_destroy (dialog);
3581 }
3582
3583 /*
3584  * Show the header details in a ModestDetailsDialog widget
3585  */
3586 void     
3587 modest_ui_actions_on_details (GtkAction *action, 
3588                               ModestWindow *win)
3589 {
3590         TnyList * headers_list;
3591         TnyIterator *iter;
3592         TnyHeader *header;              
3593
3594         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3595                 TnyMsg *msg;
3596
3597                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3598                 if (!msg)
3599                         return;
3600                 g_object_unref (msg);           
3601
3602                 headers_list = get_selected_headers (win);
3603                 if (!headers_list)
3604                         return;
3605
3606                 iter = tny_list_create_iterator (headers_list);
3607
3608                 header = TNY_HEADER (tny_iterator_get_current (iter));
3609                 if (header) {
3610                         headers_action_show_details (header, win, NULL);
3611                         g_object_unref (header);
3612                 }
3613
3614                 g_object_unref (iter);
3615                 g_object_unref (headers_list);
3616
3617         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3618                 GtkWidget *folder_view, *header_view;
3619
3620                 /* Check which widget has the focus */
3621                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3622                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3623                 if (gtk_widget_is_focus (folder_view)) {
3624                         TnyFolderStore *folder_store
3625                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3626                         if (!folder_store) {
3627                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3628                                 return; 
3629                         }
3630                         /* Show only when it's a folder */
3631                         /* This function should not be called for account items, 
3632                          * because we dim the menu item for them. */
3633                         if (TNY_IS_FOLDER (folder_store)) {
3634                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3635                         }
3636
3637                         g_object_unref (folder_store);
3638
3639                 } else {
3640                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3641                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3642                         /* Show details of each header */
3643                         do_headers_action (win, headers_action_show_details, header_view);
3644                 }
3645         }
3646 }
3647
3648 void     
3649 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3650                                      ModestMsgEditWindow *window)
3651 {
3652         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3653
3654         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3655 }
3656
3657 void     
3658 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3659                                       ModestMsgEditWindow *window)
3660 {
3661         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3662
3663         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3664 }
3665
3666 void
3667 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3668                                        ModestMainWindow *main_window)
3669 {
3670         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3671
3672         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3673                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3674         else
3675                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3676 }
3677
3678 void 
3679 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3680                                      ModestWindow *window)
3681 {
3682         gboolean active, fullscreen = FALSE;
3683         ModestWindowMgr *mgr;
3684
3685         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3686
3687         /* Check if we want to toggle the toolbar vuew in fullscreen
3688            or normal mode */
3689         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3690                      "ViewShowToolbarFullScreen")) {
3691                 fullscreen = TRUE;
3692         }
3693
3694         /* Toggle toolbar */
3695         mgr = modest_runtime_get_window_mgr ();
3696         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3697 }
3698
3699 void     
3700 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3701                                            ModestMsgEditWindow *window)
3702 {
3703         modest_msg_edit_window_select_font (window);
3704 }
3705
3706 void
3707 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3708                                                   const gchar *display_name,
3709                                                   GtkWindow *window)
3710 {
3711         /* This is usually used to change the title of the main window, which
3712          * is the one that holds the folder view. Note that this change can
3713          * happen even when the widget doesn't have the focus. */
3714         if (display_name)
3715                 gtk_window_set_title (window, display_name);
3716         else
3717                 gtk_window_set_title (window, " ");
3718 }
3719
3720 void
3721 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3722 {
3723         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3724         modest_msg_edit_window_select_contacts (window);
3725 }
3726
3727 void
3728 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3729 {
3730         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3731         modest_msg_edit_window_check_names (window, FALSE);
3732 }
3733
3734 static void
3735 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3736 {
3737         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3738                                          GTK_WIDGET (user_data));
3739 }
3740
3741 /*
3742  * This function is used to track changes in the selection of the
3743  * folder view that is inside the "move to" dialog to enable/disable
3744  * the OK button because we do not want the user to select a disallowed
3745  * destination for a folder.
3746  * The user also not desired to be able to use NEW button on items where
3747  * folder creation is not possibel.
3748  */
3749 static void
3750 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3751                                             TnyFolderStore *folder_store,
3752                                             gboolean selected,
3753                                             gpointer user_data)
3754 {
3755         GtkWidget *dialog = NULL;
3756         GtkWidget *ok_button = NULL, *new_button = NULL;
3757         GList *children = NULL;
3758         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3759         gboolean moving_folder = FALSE;
3760         gboolean is_local_account = TRUE;
3761         GtkWidget *folder_view = NULL;
3762         ModestTnyFolderRules rules;
3763
3764         if (!selected)
3765                 return;
3766
3767         /* Get the OK button */
3768         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3769         if (!dialog)
3770                 return;
3771
3772         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3773         ok_button = GTK_WIDGET (children->next->next->data);
3774         new_button = GTK_WIDGET (children->next->data);
3775         g_list_free (children);
3776
3777         /* check if folder_store is an remote account */
3778         if (TNY_IS_ACCOUNT (folder_store)) {
3779                 TnyAccount *local_account = NULL;
3780                 TnyAccount *mmc_account = NULL;
3781                 ModestTnyAccountStore *account_store = NULL;
3782
3783                 account_store = modest_runtime_get_account_store ();
3784                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3785                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3786
3787                 if ((gpointer) local_account != (gpointer) folder_store &&
3788                     (gpointer) mmc_account != (gpointer) folder_store) {
3789                         is_local_account = FALSE;
3790                         /* New button should be dimmed on remote
3791                            account root */
3792                         new_sensitive = FALSE;
3793                 }
3794                 g_object_unref (local_account);
3795         }
3796
3797         /* Check the target folder rules */
3798         if (TNY_IS_FOLDER (folder_store)) {
3799                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3800                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3801                         ok_sensitive = FALSE;
3802                         new_sensitive = FALSE;
3803                         goto end;
3804                 }
3805         }
3806
3807         /* Check if we're moving a folder */
3808         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3809                 /* Get the widgets */
3810                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3811                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3812                 if (gtk_widget_is_focus (folder_view))
3813                         moving_folder = TRUE;
3814         }
3815
3816         if (moving_folder) {
3817                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3818
3819                 /* Get the folder to move */
3820                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3821                 
3822                 /* Check that we're not moving to the same folder */
3823                 if (TNY_IS_FOLDER (moved_folder)) {
3824                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3825                         if (parent == folder_store)
3826                                 ok_sensitive = FALSE;
3827                         g_object_unref (parent);
3828                 } 
3829
3830                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3831                         /* Do not allow to move to an account unless it's the
3832                            local folders account */
3833                         if (!is_local_account)
3834                                 ok_sensitive = FALSE;
3835                 } 
3836
3837                 if (ok_sensitive && (moved_folder == folder_store)) {
3838                         /* Do not allow to move to itself */
3839                         ok_sensitive = FALSE;
3840                 }
3841                 g_object_unref (moved_folder);
3842         } else {
3843                 TnyHeader *header = NULL;
3844                 TnyFolder *src_folder = NULL;
3845
3846                 /* Moving a message */
3847                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3848                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3849                         src_folder = tny_header_get_folder (header);
3850                         g_object_unref (header);
3851                 } else {
3852                         src_folder = 
3853                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3854                 }
3855
3856                 /* Do not allow to move the msg to the same folder */
3857                 /* Do not allow to move the msg to an account */
3858                 if ((gpointer) src_folder == (gpointer) folder_store ||
3859                     TNY_IS_ACCOUNT (folder_store))
3860                         ok_sensitive = FALSE;
3861                 g_object_unref (src_folder);
3862         }
3863
3864  end:
3865         /* Set sensitivity of the OK button */
3866         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3867         /* Set sensitivity of the NEW button */
3868         gtk_widget_set_sensitive (new_button, new_sensitive);
3869 }
3870
3871 static GtkWidget*
3872 create_move_to_dialog (GtkWindow *win,
3873                        GtkWidget *folder_view,
3874                        GtkWidget **tree_view)
3875 {
3876         GtkWidget *dialog, *scroll;
3877         GtkWidget *new_button;
3878
3879         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3880                                               GTK_WINDOW (win),
3881                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3882                                               NULL);
3883
3884         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3885         /* We do this manually so GTK+ does not associate a response ID for
3886          * the button. */
3887         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3888         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3889         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3890
3891         /* Create scrolled window */
3892         scroll = gtk_scrolled_window_new (NULL, NULL);
3893         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3894                                          GTK_POLICY_AUTOMATIC,
3895                                          GTK_POLICY_AUTOMATIC);
3896
3897         /* Create folder view */
3898         *tree_view = modest_platform_create_folder_view (NULL);
3899
3900         /* Track changes in the selection to
3901          * disable the OK button whenever "Move to" is not possible
3902          * disbale NEW button whenever New is not possible */
3903         g_signal_connect (*tree_view,
3904                           "folder_selection_changed",
3905                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3906                           win);
3907
3908         /* Listen to clicks on New button */
3909         g_signal_connect (G_OBJECT (new_button), 
3910                           "clicked", 
3911                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3912                           *tree_view);
3913
3914         /* It could happen that we're trying to move a message from a
3915            window (msg window for example) after the main window was
3916            closed, so we can not just get the model of the folder
3917            view */
3918         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3919                 const gchar *visible_id = NULL;
3920
3921                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3922                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3923                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3924                                                MODEST_FOLDER_VIEW(*tree_view));
3925
3926                 visible_id = 
3927                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3928
3929                 /* Show the same account than the one that is shown in the main window */
3930                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3931                                                                              visible_id);
3932         } else {
3933                 const gchar *active_account_name = NULL;
3934                 ModestAccountMgr *mgr = NULL;
3935                 ModestAccountData *acc_data = NULL;
3936
3937                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3938                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3939                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3940                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3941
3942                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3943                 mgr = modest_runtime_get_account_mgr ();
3944                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3945
3946                 /* Set the new visible & active account */
3947                 if (acc_data && acc_data->store_account) { 
3948                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3949                                                                                      acc_data->store_account->account_name);
3950                         modest_account_mgr_free_account_data (mgr, acc_data);
3951                 }
3952         }
3953
3954         /* Hide special folders */
3955         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3956         
3957         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3958
3959         /* Add scroll to dialog */
3960         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3961                             scroll, TRUE, TRUE, 0);
3962
3963         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3964         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3965
3966         return dialog;
3967 }
3968
3969 /*
3970  * Returns TRUE if at least one of the headers of the list belongs to
3971  * a message that has been fully retrieved.
3972  */
3973 #if 0 /* no longer in use. delete in 2007.10 */
3974 static gboolean
3975 has_retrieved_msgs (TnyList *list)
3976 {
3977         TnyIterator *iter;
3978         gboolean found = FALSE;
3979
3980         iter = tny_list_create_iterator (list);
3981         while (!tny_iterator_is_done (iter) && !found) {
3982                 TnyHeader *header;
3983                 TnyHeaderFlags flags = 0;
3984
3985                 header = TNY_HEADER (tny_iterator_get_current (iter));
3986                 if (header) {
3987                         flags = tny_header_get_flags (header);
3988                         if (flags & TNY_HEADER_FLAG_CACHED)
3989 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3990                                 found = TRUE;
3991
3992                         g_object_unref (header);
3993                 }
3994
3995                 if (!found)
3996                         tny_iterator_next (iter);
3997         }
3998         g_object_unref (iter);
3999
4000         return found;
4001 }
4002 #endif /* 0 */
4003
4004
4005 /*
4006  * Shows a confirmation dialog to the user when we're moving messages
4007  * from a remote server to the local storage. Returns the dialog
4008  * response. If it's other kind of movement then it always returns
4009  * GTK_RESPONSE_OK
4010  *
4011  * This one is used by the next functions:
4012  *      modest_ui_actions_on_paste                      - commented out
4013  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4014  */
4015 gint
4016 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4017                                              TnyFolder *dest_folder,
4018                                              gboolean delete,
4019                                              TnyList *headers)
4020 {
4021         gint response = GTK_RESPONSE_OK;
4022         TnyAccount *account = NULL;
4023         TnyFolder *src_folder = NULL;
4024         TnyIterator *iter = NULL;
4025         TnyHeader *header = NULL;
4026
4027         /* return with OK if the destination is a remote folder */
4028         if (modest_tny_folder_is_remote_folder (dest_folder))
4029                 return GTK_RESPONSE_OK;
4030
4031         /* Get source folder */
4032         iter = tny_list_create_iterator (headers);
4033         header = TNY_HEADER (tny_iterator_get_current (iter));
4034         if (header) {
4035                 src_folder = tny_header_get_folder (header);
4036                 g_object_unref (header);
4037         }
4038         g_object_unref (iter);
4039
4040         /* if no src_folder, message may be an attahcment */
4041         if (src_folder == NULL) 
4042                 return GTK_RESPONSE_CANCEL;
4043
4044         /* If the source is a local or MMC folder */
4045         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4046                 g_object_unref (src_folder);
4047                 return GTK_RESPONSE_OK;
4048         }
4049
4050         /* Get the account */
4051         account = tny_folder_get_account (src_folder);
4052
4053         /* now if offline we ask the user */
4054         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4055                 response = GTK_RESPONSE_OK;
4056         else
4057                 response = GTK_RESPONSE_CANCEL;
4058
4059         /* Frees */
4060         g_object_unref (src_folder);
4061         g_object_unref (account);
4062
4063         return response;
4064 }
4065
4066
4067
4068 static void
4069 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
4070 {
4071         MoveToHelper *helper = (MoveToHelper *) user_data;
4072
4073         /* Note that the operation could have failed, in that case do
4074            nothing */
4075         if (modest_mail_operation_get_status (mail_op) == 
4076             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4077
4078                 GObject *object = modest_mail_operation_get_source (mail_op);
4079                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4080                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4081
4082                         if (!modest_msg_view_window_select_next_message (self))
4083                                 if (!modest_msg_view_window_select_previous_message (self))
4084                                         /* No more messages to view, so close this window */
4085                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4086                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4087                         GtkWidget *header_view;
4088                         GtkTreePath *path;
4089                         GtkTreeSelection *sel;
4090
4091                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4092                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4093                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4094                         path = gtk_tree_row_reference_get_path (helper->reference);
4095                         gtk_tree_selection_select_path (sel, path);
4096                         gtk_tree_path_free (path);
4097                 }
4098                 g_object_unref (object);
4099         }
4100
4101         /* Close the "Pasting" information banner */
4102         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4103         if (helper->reference != NULL)
4104                 gtk_tree_row_reference_free (helper->reference);
4105         g_free (helper);
4106 }
4107
4108 void
4109 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4110                                              gpointer user_data)
4111 {
4112         ModestWindow *main_window = NULL;
4113         GObject *win = NULL;
4114         const GError *error = NULL;
4115         const gchar *message = NULL;
4116         
4117         /* Get error message */
4118         error = modest_mail_operation_get_error (mail_op);
4119         if (error != NULL && error->message != NULL) {
4120                 message = error->message;
4121         } else {
4122                 message = _("mail_in_ui_folder_move_target_error");
4123         }
4124         
4125         /* Disable next automatic folder selection */
4126         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4127                                                          FALSE); /* don't create */
4128         if (main_window) {
4129                 GtkWidget *folder_view = NULL;
4130         
4131                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4132                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4133                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4134                 
4135                 if (user_data && TNY_IS_FOLDER (user_data)) {
4136                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4137                                                           TNY_FOLDER (user_data), FALSE);
4138                 }
4139         }
4140
4141         /* Show notification dialog */
4142         win = modest_mail_operation_get_source (mail_op);
4143         modest_platform_run_information_dialog ((GtkWindow *) win, message);
4144         if (win)
4145                 g_object_unref (win);
4146 }
4147
4148 void
4149 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4150                                               gpointer user_data)
4151 {
4152         GObject *win = modest_mail_operation_get_source (mail_op);
4153         const GError *error = modest_mail_operation_get_error (mail_op);
4154
4155         g_return_if_fail (error != NULL);
4156         if (error->message != NULL)             
4157                 g_printerr ("modest: %s\n", error->message);
4158         else
4159                 g_printerr ("modest: unkonw error on send&receive operation");
4160
4161         /* Show error message */
4162 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4163 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4164 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4165 /*      else  */
4166 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4167 /*                                                      _CS("sfil_ib_unable_to_send")); */
4168         g_object_unref (win);
4169 }
4170
4171 static void
4172 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4173                        TnyHeader *header, 
4174                        gboolean canceled,
4175                        TnyMsg *msg, 
4176                        GError *err,
4177                        gpointer user_data)
4178 {
4179         TnyList *parts;
4180         TnyIterator *iter;
4181         gint pending_purges = 0;
4182         gboolean some_purged = FALSE;
4183         ModestWindow *win = MODEST_WINDOW (user_data);
4184         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4185
4186         /* If there was any error */
4187         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4188                 modest_window_mgr_unregister_header (mgr, header);
4189                 return;
4190         }
4191
4192         /* Once the message has been retrieved for purging, we check if
4193          * it's all ok for purging */
4194
4195         parts = tny_simple_list_new ();
4196         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4197         iter = tny_list_create_iterator (parts);
4198
4199         while (!tny_iterator_is_done (iter)) {
4200                 TnyMimePart *part;
4201                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4202                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4203                         if (tny_mime_part_is_purged (part))
4204                                 some_purged = TRUE;
4205                         else
4206                                 pending_purges++;
4207                 }
4208
4209                 if (part)
4210                         g_object_unref (part);
4211
4212                 tny_iterator_next (iter);
4213         }
4214         g_object_unref (iter);
4215         
4216
4217         if (pending_purges>0) {
4218                 gint response;
4219                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4220
4221                 if (response == GTK_RESPONSE_OK) {
4222                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4223                         iter = tny_list_create_iterator (parts);
4224                         while (!tny_iterator_is_done (iter)) {
4225                                 TnyMimePart *part;
4226                                 
4227                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4228                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4229                                         tny_mime_part_set_purged (part);
4230
4231                                 if (part)
4232                                         g_object_unref (part);
4233
4234                                 tny_iterator_next (iter);
4235                         }
4236                         
4237                         tny_msg_rewrite_cache (msg);
4238                 }
4239      /* } else { */
4240                 /* This string no longer exists, refer to NB#75415 for more info */
4241                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4242         }
4243         g_object_unref (iter);
4244
4245         modest_window_mgr_unregister_header (mgr, header);
4246
4247         g_object_unref (parts);
4248 }
4249
4250 static void
4251 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4252                                                      ModestMainWindow *win)
4253 {
4254         GtkWidget *header_view;
4255         TnyList *header_list;
4256         TnyIterator *iter;
4257         TnyHeader *header;
4258         TnyHeaderFlags flags;
4259         ModestWindow *msg_view_window =  NULL;
4260         gboolean found;
4261
4262         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4263
4264         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4265                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4266
4267         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4268         if (!header_list) {
4269                 g_warning ("%s: no header selected", __FUNCTION__);
4270                 return;
4271         }
4272         
4273         if (tny_list_get_length (header_list) == 1) {
4274                 iter = tny_list_create_iterator (header_list);
4275                 header = TNY_HEADER (tny_iterator_get_current (iter));
4276                 g_object_unref (iter);
4277         } else
4278                 return;
4279         
4280         if (!header || !TNY_IS_HEADER(header)) {
4281                 g_warning ("%s: header is not valid", __FUNCTION__);
4282                 return;
4283         }
4284         
4285         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4286                                                           header, &msg_view_window);
4287         flags = tny_header_get_flags (header);
4288         if (!(flags & TNY_HEADER_FLAG_CACHED))
4289                 return;
4290         if (found) {
4291                 if (msg_view_window != NULL) 
4292                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4293                 else {
4294                         /* do nothing; uid was registered before, so window is probably on it's way */
4295                         g_warning ("debug: header %p has already been registered", header);
4296                 }
4297         } else {
4298                 ModestMailOperation *mail_op = NULL;
4299                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4300                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4301                                                                          modest_ui_actions_get_msgs_full_error_handler,
4302                                                                          NULL, NULL);
4303                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4304                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4305                 
4306                 g_object_unref (mail_op);
4307         }
4308         if (header)
4309                 g_object_unref (header);
4310         if (header_list)
4311                 g_object_unref (header_list);
4312 }
4313
4314 /**
4315  * Utility function that transfer messages from both the main window
4316  * and the msg view window when using the "Move to" dialog
4317  */
4318 static void
4319 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4320                                               ModestWindow *win)
4321 {
4322         TnyList *headers = NULL;
4323         TnyAccount *dst_account = NULL;
4324         const gchar *proto_str = NULL;
4325         gboolean dst_is_pop = FALSE;
4326
4327         if (!TNY_IS_FOLDER (dst_folder)) {
4328                 modest_platform_information_banner (GTK_WIDGET (win),
4329                                                     NULL,
4330                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4331                 return;
4332         }
4333
4334         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4335         proto_str = tny_account_get_proto (dst_account);
4336
4337         /* tinymail will return NULL for local folders it seems */
4338         dst_is_pop = proto_str &&
4339                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4340                  MODEST_PROTOCOL_STORE_POP);
4341
4342         g_object_unref (dst_account);
4343
4344         /* Get selected headers */
4345         headers = get_selected_headers (MODEST_WINDOW (win));
4346         if (!headers) {
4347                 g_warning ("%s: no headers selected", __FUNCTION__);
4348                 return;
4349         }
4350
4351
4352         if (dst_is_pop) {
4353                 modest_platform_information_banner (GTK_WIDGET (win),
4354                                                     NULL,
4355                                                     ngettext("mail_in_ui_folder_move_target_error",
4356                                                              "mail_in_ui_folder_move_targets_error",
4357                                                              tny_list_get_length (headers)));
4358                 g_object_unref (headers);
4359                 return;
4360         }
4361
4362         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4363         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4364                                                            _CS("ckct_nw_pasting"));
4365         if (helper->banner != NULL)  {
4366                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4367                 gtk_widget_show (GTK_WIDGET(helper->banner));
4368         }
4369
4370         if (MODEST_IS_MAIN_WINDOW (win)) {
4371                 GtkWidget *header_view = 
4372                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4373                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4374                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4375         }
4376
4377         ModestMailOperation *mail_op = 
4378                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4379                                                                modest_ui_actions_move_folder_error_handler,
4380                                                                NULL, NULL);
4381         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4382                                          mail_op);
4383
4384         modest_mail_operation_xfer_msgs (mail_op, 
4385                                          headers,
4386                                          TNY_FOLDER (dst_folder),
4387                                          TRUE,
4388                                          move_to_cb,
4389                                          helper);
4390
4391         g_object_unref (G_OBJECT (mail_op));
4392         g_object_unref (headers);
4393 }
4394
4395 /*
4396  * UI handler for the "Move to" action when invoked from the
4397  * ModestMainWindow
4398  */
4399 static void 
4400 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4401                                           GtkWidget *folder_view,
4402                                           TnyFolderStore *dst_folder,
4403                                           ModestMainWindow *win)
4404 {
4405         ModestHeaderView *header_view = NULL;
4406         ModestMailOperation *mail_op = NULL;
4407         TnyFolderStore *src_folder;
4408         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4409
4410         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4411
4412         /* Get the source folder */
4413         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4414
4415         /* Get header view */
4416         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4417
4418         /* Get folder or messages to transfer */
4419         if (gtk_widget_is_focus (folder_view)) {
4420                 GtkTreeSelection *sel;
4421                 gboolean do_xfer = TRUE;
4422
4423                 /* Allow only to transfer folders to the local root folder */
4424                 if (TNY_IS_ACCOUNT (dst_folder) && 
4425                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4426                         do_xfer = FALSE;
4427                 } else if (!TNY_IS_FOLDER (src_folder)) {
4428                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4429                         do_xfer = FALSE;
4430                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4431                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4432                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4433                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4434                                 do_xfer = FALSE;
4435                         g_object_unref (account);
4436                 }
4437
4438                 if (do_xfer) {
4439                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4440                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4441                                                                            _CS("ckct_nw_pasting"));
4442                         if (helper->banner != NULL)  {
4443                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4444                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4445                         }
4446                         /* Clean folder on header view before moving it */
4447                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4448                         gtk_tree_selection_unselect_all (sel);
4449
4450                         /* Let gtk events run. We need that the folder
4451                            view frees its reference to the source
4452                            folder *before* issuing the mail operation
4453                            so we need the signal handler of selection
4454                            changed to happen before the mail
4455                            operation */
4456                         while (gtk_events_pending ())
4457                                 gtk_main_iteration ();
4458
4459                         mail_op =
4460                           modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4461                                                                          modest_ui_actions_move_folder_error_handler,
4462                                                                          src_folder, NULL);
4463                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4464                                                          mail_op);
4465
4466                         /* Select *after* the changes */
4467                         /* TODO: this function hangs UI after transfer */ 
4468 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4469 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4470                         
4471                         modest_mail_operation_xfer_folder (mail_op,
4472                                                            TNY_FOLDER (src_folder),
4473                                                            dst_folder,
4474                                                            TRUE, 
4475                                                            move_to_cb, 
4476                                                            helper);
4477                         /* Unref mail operation */
4478                         g_object_unref (G_OBJECT (mail_op));
4479                 }
4480         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4481                 gboolean do_xfer = TRUE;
4482                 /* Ask for confirmation if the source folder is remote and we're not connected */
4483                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4484                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4485                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4486                                 guint num_headers = tny_list_get_length(headers);
4487                                 TnyAccount *account = get_account_from_header_list (headers);
4488                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4489                                         do_xfer = FALSE;
4490                                 g_object_unref (account);
4491                         }
4492                         g_object_unref(headers);
4493                 }
4494                 if (do_xfer) /* Transfer messages */
4495                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4496         }
4497
4498     if (src_folder)
4499         g_object_unref (src_folder);
4500 }
4501
4502
4503 /*
4504  * UI handler for the "Move to" action when invoked from the
4505  * ModestMsgViewWindow
4506  */
4507 static void 
4508 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4509                                               TnyFolderStore *dst_folder,
4510                                               ModestMsgViewWindow *win)
4511 {
4512         TnyHeader *header = NULL;
4513         TnyFolder *src_folder = NULL;
4514         TnyAccount *account = NULL;
4515         gboolean do_xfer = FALSE;
4516
4517         /* Create header list */
4518         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4519         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4520         g_object_unref (header);
4521
4522         account = tny_folder_get_account (src_folder);
4523         if (!modest_platform_is_network_folderstore(TNY_FOLDER_STORE(src_folder))) {
4524                 /* Transfer if the source folder is local */
4525                 do_xfer = TRUE;
4526         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4527                 /* Transfer if the source folder is POP (as it means
4528                  * that the message is already downloaded) */
4529                 do_xfer = TRUE;
4530         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4531                 /* Transfer after asking confirmation */
4532                 do_xfer = TRUE;
4533         }
4534
4535         if (do_xfer) {
4536                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4537         }
4538         g_object_unref (account);
4539         g_object_unref (src_folder);
4540 }
4541
4542 void 
4543 modest_ui_actions_on_move_to (GtkAction *action, 
4544                               ModestWindow *win)
4545 {
4546         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4547         gint result = 0;
4548         TnyFolderStore *dst_folder = NULL;
4549         ModestMainWindow *main_window;
4550
4551         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4552                           MODEST_IS_MSG_VIEW_WINDOW (win));
4553
4554         /* Get the main window if exists */
4555         if (MODEST_IS_MAIN_WINDOW (win))
4556                 main_window = MODEST_MAIN_WINDOW (win);
4557         else
4558                 main_window = 
4559                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4560                                                                                FALSE)); /* don't create */
4561
4562         /* Get the folder view widget if exists */
4563         if (main_window)
4564                 folder_view = modest_main_window_get_child_widget (main_window,
4565                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4566         else
4567                 folder_view = NULL;
4568
4569         /* Create and run the dialog */
4570         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4571         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4572         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4573         result = gtk_dialog_run (GTK_DIALOG(dialog));
4574         g_object_ref (tree_view);
4575         gtk_widget_destroy (dialog);
4576
4577         if (result != GTK_RESPONSE_ACCEPT)
4578                 return;
4579
4580         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4581         /* Do window specific stuff */
4582         if (MODEST_IS_MAIN_WINDOW (win)) {
4583                 modest_ui_actions_on_main_window_move_to (action,
4584                                                           folder_view,
4585                                                           dst_folder,
4586                                                           MODEST_MAIN_WINDOW (win));
4587         } else {
4588                 modest_ui_actions_on_msg_view_window_move_to (action,
4589                                                               dst_folder,
4590                                                               MODEST_MSG_VIEW_WINDOW (win));
4591         }
4592
4593         if (dst_folder)
4594                 g_object_unref (dst_folder);
4595 }
4596
4597 /*
4598  * Calls #HeadersFunc for each header already selected in the main
4599  * window or the message currently being shown in the msg view window
4600  */
4601 static void
4602 do_headers_action (ModestWindow *win, 
4603                    HeadersFunc func,
4604                    gpointer user_data)
4605 {
4606         TnyList *headers_list = NULL;
4607         TnyIterator *iter = NULL;
4608         TnyHeader *header = NULL;
4609         TnyFolder *folder = NULL;
4610
4611         /* Get headers */
4612         headers_list = get_selected_headers (win);
4613         if (!headers_list)
4614                 return;
4615
4616         /* Get the folder */
4617         iter = tny_list_create_iterator (headers_list);
4618         header = TNY_HEADER (tny_iterator_get_current (iter));
4619         if (header) {
4620                 folder = tny_header_get_folder (header);
4621                 g_object_unref (header);
4622         }
4623
4624         /* Call the function for each header */
4625         while (!tny_iterator_is_done (iter)) {
4626                 header = TNY_HEADER (tny_iterator_get_current (iter));
4627                 func (header, win, user_data);
4628                 g_object_unref (header);
4629                 tny_iterator_next (iter);
4630         }
4631
4632         /* Trick: do a poke status in order to speed up the signaling
4633            of observers */
4634         tny_folder_poke_status (folder);
4635
4636         /* Frees */
4637         g_object_unref (folder);
4638         g_object_unref (iter);
4639         g_object_unref (headers_list);
4640 }
4641
4642 void 
4643 modest_ui_actions_view_attachment (GtkAction *action,
4644                                    ModestWindow *window)
4645 {
4646         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4647                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4648         } else {
4649                 /* not supported window for this action */
4650                 g_return_if_reached ();
4651         }
4652 }
4653
4654 void
4655 modest_ui_actions_save_attachments (GtkAction *action,
4656                                     ModestWindow *window)
4657 {
4658         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4659                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4660         } else {
4661                 /* not supported window for this action */
4662                 g_return_if_reached ();
4663         }
4664 }
4665
4666 void
4667 modest_ui_actions_remove_attachments (GtkAction *action,
4668                                       ModestWindow *window)
4669 {
4670         if (MODEST_IS_MAIN_WINDOW (window)) {
4671                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4672         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4673                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4674         } else {
4675                 /* not supported window for this action */
4676                 g_return_if_reached ();
4677         }
4678 }
4679
4680 void 
4681 modest_ui_actions_on_settings (GtkAction *action, 
4682                                ModestWindow *win)
4683 {
4684         GtkWidget *dialog;
4685
4686         dialog = modest_platform_get_global_settings_dialog ();
4687         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4688         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4689         gtk_widget_show_all (dialog);
4690
4691         gtk_dialog_run (GTK_DIALOG (dialog));
4692
4693         gtk_widget_destroy (dialog);
4694 }
4695
4696 void 
4697 modest_ui_actions_on_help (GtkAction *action, 
4698                            GtkWindow *win)
4699 {
4700         const gchar *help_id;
4701
4702         g_return_if_fail (action);
4703         g_return_if_fail (win && GTK_IS_WINDOW(win));
4704         
4705         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4706         
4707         if (help_id)
4708                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4709         else
4710                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4711 }
4712
4713 static void
4714 retrieve_msg_contents_performer (gboolean canceled, 
4715                                  GError *err,
4716                                  GtkWindow *parent_window, 
4717                                  TnyAccount *account, 
4718                                  gpointer user_data)
4719 {
4720         ModestMailOperation *mail_op;
4721         TnyList *headers = TNY_LIST (user_data);
4722
4723         if (err || canceled) {
4724                 /* Show an error ? */
4725                 goto out;
4726         }
4727
4728         /* Create mail operation */
4729         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
4730                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4731                                                                  NULL, NULL);
4732         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4733         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4734
4735         /* Frees */
4736         g_object_unref (mail_op);
4737  out:
4738         g_object_unref (headers);
4739         g_object_unref (account);
4740 }
4741
4742 void 
4743 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4744                                             ModestWindow *window)
4745 {
4746         TnyList *headers = NULL;
4747         TnyAccount *account = NULL;
4748         TnyIterator *iter = NULL;
4749         TnyHeader *header = NULL;
4750         TnyFolder *folder = NULL;
4751
4752         /* Get headers */
4753         headers = get_selected_headers (window);
4754         if (!headers)
4755                 return;
4756
4757         /* Pick the account */
4758         iter = tny_list_create_iterator (headers);
4759         header = TNY_HEADER (tny_iterator_get_current (iter));
4760         folder = tny_header_get_folder (header);
4761         account = tny_folder_get_account (folder);
4762         g_object_unref (folder);
4763         g_object_unref (header);
4764         g_object_unref (iter);
4765
4766         /* Connect and perform the message retrieval */
4767         modest_platform_connect_and_perform ((GtkWindow *) window, 
4768                                              g_object_ref (account), 
4769                                              retrieve_msg_contents_performer, 
4770                                              g_object_ref (headers));
4771
4772         /* Frees */
4773         g_object_unref (account);
4774         g_object_unref (headers);
4775 }
4776
4777 void
4778 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4779                                           ModestWindow *window)
4780 {
4781         g_return_if_fail (MODEST_IS_WINDOW (window));
4782         
4783         /* Update dimmed */     
4784         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4785 }
4786
4787 void
4788 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4789                                           ModestWindow *window)
4790 {
4791         g_return_if_fail (MODEST_IS_WINDOW (window));
4792
4793         /* Update dimmed */     
4794         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4795 }
4796
4797 void
4798 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4799                                           ModestWindow *window)
4800 {
4801         g_return_if_fail (MODEST_IS_WINDOW (window));
4802
4803         /* Update dimmed */     
4804         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4805 }
4806
4807 void
4808 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4809                                             ModestWindow *window)
4810 {
4811         g_return_if_fail (MODEST_IS_WINDOW (window));
4812
4813         /* Update dimmed */     
4814         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4815 }
4816
4817 void
4818 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4819                                           ModestWindow *window)
4820 {
4821         g_return_if_fail (MODEST_IS_WINDOW (window));
4822
4823         /* Update dimmed */     
4824         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4825 }
4826
4827 void
4828 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4829                                           ModestWindow *window)
4830 {
4831         g_return_if_fail (MODEST_IS_WINDOW (window));
4832
4833         /* Update dimmed */     
4834         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4835 }
4836
4837 void
4838 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4839                                                  ModestWindow *window)
4840 {
4841         g_return_if_fail (MODEST_IS_WINDOW (window));
4842
4843         /* Update dimmed */     
4844         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4845 }
4846
4847 void
4848 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4849                                                      ModestWindow *window)
4850 {
4851         g_return_if_fail (MODEST_IS_WINDOW (window));
4852
4853         /* Update dimmed */     
4854         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4855 }
4856
4857 void
4858 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4859                                                      ModestWindow *window)
4860 {
4861         g_return_if_fail (MODEST_IS_WINDOW (window));
4862
4863         /* Update dimmed */     
4864         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4865 }
4866
4867 void
4868 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4869 {
4870         g_return_if_fail (MODEST_IS_WINDOW (window));
4871
4872         /* Update dimmed */     
4873         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4874 }
4875
4876 void
4877 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4878 {
4879         g_return_if_fail (MODEST_IS_WINDOW (window));
4880
4881         modest_platform_show_search_messages (GTK_WINDOW (window));
4882 }
4883
4884 void     
4885 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4886 {
4887         g_return_if_fail (MODEST_IS_WINDOW (win));
4888         modest_platform_show_addressbook (GTK_WINDOW (win));
4889 }
4890
4891
4892 void
4893 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4894                                           ModestWindow *window)
4895 {
4896         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4897
4898         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4899 }
4900
4901 static void 
4902 on_send_receive_finished (ModestMailOperation  *mail_op, 
4903                            gpointer user_data)
4904 {
4905         GtkWidget *header_view, *folder_view;
4906         TnyFolderStore *folder_store;
4907         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
4908
4909         /* Set send/receive operation finished */       
4910         modest_main_window_notify_send_receive_completed (main_win);
4911
4912         /* Don't refresh the current folder if there were any errors */
4913         if (modest_mail_operation_get_status (mail_op) !=
4914             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4915                 return;
4916         
4917         /* Refresh the current folder if we're viewing a window. We do
4918            this because the user won't be able to see the new mails in
4919            the selected folder after a Send&Receive because it only
4920            performs a poke_status, i.e, only the number of read/unread
4921            messages is updated, but the new headers are not
4922            downloaded */
4923         folder_view = modest_main_window_get_child_widget (main_win, 
4924                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4925         if (!folder_view)
4926                 return;
4927
4928         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4929         
4930         /* Do not need to refresh INBOX again because the
4931            update_account does it always automatically */
4932         if (folder_store && TNY_IS_FOLDER (folder_store) && 
4933             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
4934
4935                 header_view = modest_main_window_get_child_widget (main_win,
4936                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4937                 
4938                 /* We do not need to set the contents style
4939                    because it hasn't changed. We also do not
4940                    need to save the widget status. Just force
4941                    a refresh */
4942                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
4943                                                TNY_FOLDER (folder_store),
4944                                                folder_refreshed_cb,
4945                                                main_win);
4946         }
4947         
4948         if (folder_store)
4949                 g_object_unref (folder_store);
4950 }
4951
4952
4953 void 
4954 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4955                                                 TnyHeader *header, 
4956                                                 TnyMsg *msg, 
4957                                                 GError *err, 
4958                                                 gpointer user_data)
4959 {
4960         const gchar* server_name = NULL;
4961         TnyTransportAccount *server_account;
4962         gchar *message = NULL;
4963
4964         /* Don't show anything if the user cancelled something */
4965         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4966                 return;
4967
4968         /* Get the server name: */
4969         server_account = 
4970                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4971         if (server_account) {
4972                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4973                         
4974                 g_object_unref (server_account);
4975                 server_account = NULL;
4976         }
4977         
4978         g_return_if_fail (server_name);
4979
4980         /* Show the appropriate message text for the GError: */
4981         switch (err->code) {
4982         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4983                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4984                 break;
4985         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4986                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4987                 break;
4988         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4989                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4990                 break;
4991         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4992                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4993                 break;
4994         default:
4995                 g_return_if_reached ();
4996         }
4997         
4998         /* TODO if the username or the password where not defined we
4999            should show the Accounts Settings dialog or the Connection
5000            specific SMTP server window */
5001
5002         modest_platform_run_information_dialog (NULL, message);
5003         g_free (message);
5004 }
5005
5006 void
5007 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5008                                                 gchar *msg_id, 
5009                                                 guint status,
5010                                                 gpointer user_data)
5011 {
5012         ModestMainWindow *main_window = NULL;
5013         ModestWindowMgr *mgr = NULL;
5014         GtkWidget *folder_view = NULL, *header_view = NULL;
5015         TnyFolderStore *selected_folder = NULL;
5016         TnyFolderType folder_type;
5017
5018         mgr = modest_runtime_get_window_mgr ();
5019         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5020                                                                              FALSE));/* don't create */
5021         if (!main_window)
5022                 return;
5023
5024         /* Check if selected folder is OUTBOX */
5025         folder_view = modest_main_window_get_child_widget (main_window,
5026                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5027         header_view = modest_main_window_get_child_widget (main_window,
5028                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5029
5030         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5031         if (!TNY_IS_FOLDER (selected_folder)) 
5032                 goto frees;
5033
5034         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5035 #if GTK_CHECK_VERSION(2, 8, 0) 
5036         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5037         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5038                 GtkTreeViewColumn *tree_column;
5039
5040                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5041                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5042                 gtk_tree_view_column_queue_resize (tree_column);
5043         }
5044 #else
5045         gtk_widget_queue_draw (header_view);
5046 #endif          
5047         
5048         /* Free */
5049  frees:
5050         if (selected_folder != NULL)
5051                 g_object_unref (selected_folder);
5052 }
5053
5054 void 
5055 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5056                                                TnyAccount *account)
5057 {
5058         ModestTransportStoreProtocol proto;
5059         const gchar *proto_name;
5060         gchar *error_note = NULL;
5061         
5062         proto_name = tny_account_get_proto (account);
5063         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5064         
5065         switch (proto) {
5066         case MODEST_PROTOCOL_STORE_POP:
5067                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5068                                               tny_account_get_hostname (account));
5069                 break;
5070         case MODEST_PROTOCOL_STORE_IMAP:
5071                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5072                                               tny_account_get_hostname (account));
5073                 break;
5074         case MODEST_PROTOCOL_STORE_MAILDIR:
5075         case MODEST_PROTOCOL_STORE_MBOX:
5076                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5077                 break;
5078         default:
5079                 g_warning ("%s: This should not be reached", __FUNCTION__);
5080         }
5081
5082         if (error_note) {
5083                 modest_platform_run_information_dialog (parent_window, error_note);
5084                 g_free (error_note);
5085         }
5086 }