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