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