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