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