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