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