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