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