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