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