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