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