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