* Fixes NB#75550, after deleting a folder the focus is not set over the INBOX
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         GtkTreeRowReference *reference;
108         GtkWidget *banner;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
144                                           gpointer user_data);
145
146 static gint header_list_count_uncached_msgs (TnyList *header_list);
147
148 static gboolean connect_to_get_msg (ModestWindow *win,
149                                     gint num_of_uncached_msgs,
150                                     TnyAccount *account);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200
201 /* FIXME: this should be merged with the similar code in modest-account-view-window */
202 /* Show the account creation wizard dialog.
203  * returns: TRUE if an account was created. FALSE if the user cancelled.
204  */
205 gboolean
206 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
207 {
208         gboolean result = FALSE;        
209         GtkWindow *dialog, *wizard;
210         gint dialog_response;
211
212         /* Show the easy-setup wizard: */       
213         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
214         if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) {
215                 /* old wizard is active already; 
216                  */
217                 gtk_window_present (GTK_WINDOW(dialog));
218                 return FALSE;
219         }
220         
221
222         /* there is no such wizard yet */       
223         wizard = GTK_WINDOW (modest_easysetup_wizard_dialog_new ());
224         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
225
226         /* always present a main window in the background 
227          * we do it here, so we cannot end up with two wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win) 
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
231                                                          TRUE);  /* create if not existent */
232         
233         /* make sure the mainwindow is visible */
234         gtk_widget_show_all (GTK_WIDGET(win));
235         gtk_window_present (GTK_WINDOW(win));
236         
237         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
238         gtk_widget_destroy (GTK_WIDGET (wizard));
239         if (gtk_events_pending ())
240                 gtk_main_iteration ();
241
242         if (dialog_response == GTK_RESPONSE_CANCEL) {
243                 result = FALSE;
244         } else {
245                 /* Check whether an account was created: */
246                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
247         }
248         
249         return result;
250 }
251
252
253 void   
254 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
255 {
256         GtkWidget *about;
257         const gchar *authors[] = {
258                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
259                 NULL
260         };
261         about = gtk_about_dialog_new ();
262         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
263         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
264         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
265                                         _("Copyright (c) 2006, Nokia Corporation\n"
266                                           "All rights reserved."));
267         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
268                                        _("a modest e-mail client\n\n"
269                                          "design and implementation: Dirk-Jan C. Binnema\n"
270                                          "contributions from the fine people at KC and Ig\n"
271                                          "uses the tinymail email framework written by Philip van Hoof"));
272         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
273         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
274         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
275         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
276         
277         gtk_dialog_run (GTK_DIALOG (about));
278         gtk_widget_destroy(about);
279 }
280
281 /*
282  * Gets the list of currently selected messages. If the win is the
283  * main window, then it returns a newly allocated list of the headers
284  * selected in the header view. If win is the msg view window, then
285  * the value returned is a list with just a single header.
286  *
287  * The caller of this funcion must free the list.
288  */
289 static TnyList *
290 get_selected_headers (ModestWindow *win)
291 {
292         if (MODEST_IS_MAIN_WINDOW(win)) {
293                 GtkWidget *header_view;         
294                 
295                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
296                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
297                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
298                 
299         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
300                 /* for MsgViewWindows, we simply return a list with one element */
301                 TnyHeader *header;
302                 TnyList *list = NULL;
303                 
304                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
305                 if (header != NULL) {
306                         list = tny_simple_list_new ();
307                         tny_list_prepend (list, G_OBJECT(header));
308                         g_object_unref (G_OBJECT(header));
309                 }
310
311                 return list;
312
313         } else
314                 return NULL;
315 }
316
317 static GtkTreeRowReference *
318 get_next_after_selected_headers (ModestHeaderView *header_view)
319 {
320         GtkTreeSelection *sel;
321         GList *selected_rows, *node;
322         GtkTreePath *path;
323         GtkTreeRowReference *result;
324         GtkTreeModel *model;
325
326         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
327         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
328         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
329
330         if (selected_rows == NULL)
331                 return NULL;
332
333         node = g_list_last (selected_rows);
334         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
335         gtk_tree_path_next (path);
336
337         result = gtk_tree_row_reference_new (model, path);
338
339         gtk_tree_path_free (path);
340         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
341         g_list_free (selected_rows);
342
343         return result;
344 }
345
346 static void
347 headers_action_mark_as_read (TnyHeader *header,
348                              ModestWindow *win,
349                              gpointer user_data)
350 {
351         TnyHeaderFlags flags;
352
353         g_return_if_fail (TNY_IS_HEADER(header));
354
355         flags = tny_header_get_flags (header);
356         if (flags & TNY_HEADER_FLAG_SEEN) return;
357         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
358 }
359
360 static void
361 headers_action_mark_as_unread (TnyHeader *header,
362                                ModestWindow *win,
363                                gpointer user_data)
364 {
365         TnyHeaderFlags flags;
366
367         g_return_if_fail (TNY_IS_HEADER(header));
368
369         flags = tny_header_get_flags (header);
370         if (flags & TNY_HEADER_FLAG_SEEN)  {
371                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
372         }
373 }
374
375 /** After deleing a message that is currently visible in a window, 
376  * show the next message from the list, or close the window if there are no more messages.
377  **/
378 void 
379 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
380 {
381         /* Close msg view window or select next */
382         if (modest_msg_view_window_last_message_selected (win) &&
383                 modest_msg_view_window_first_message_selected (win)) {
384                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
385         } else if (!modest_msg_view_window_select_next_message (win)) {
386                 gboolean ret_value;
387                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
388         }
389 }
390
391
392 void
393 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
394 {
395         TnyList *header_list = NULL;
396         TnyIterator *iter = NULL;
397         TnyHeader *header = NULL;
398         gchar *message = NULL;
399         gchar *desc = NULL;
400         gint response;
401         ModestWindowMgr *mgr;
402         GtkWidget *header_view = NULL;
403
404         g_return_if_fail (MODEST_IS_WINDOW(win));
405         
406         /* Check first if the header view has the focus */
407         if (MODEST_IS_MAIN_WINDOW (win)) {
408                 header_view = 
409                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
410                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
411                 if (!gtk_widget_is_focus (header_view))
412                         return;
413         }
414         
415         /* Get the headers, either from the header view (if win is the main window),
416          * or from the message view window: */
417         header_list = get_selected_headers (win);
418         if (!header_list) return;
419                         
420         /* Check if any of the headers are already opened, or in the process of being opened */
421         if (MODEST_IS_MAIN_WINDOW (win)) {
422                 gint opened_headers = 0;
423
424                 iter = tny_list_create_iterator (header_list);
425                 mgr = modest_runtime_get_window_mgr ();
426                 while (!tny_iterator_is_done (iter)) {
427                         header = TNY_HEADER (tny_iterator_get_current (iter));
428                         if (header) {
429                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
430                                         opened_headers++;
431                                 g_object_unref (header);
432                         }
433                         tny_iterator_next (iter);
434                 }
435                 g_object_unref (iter);
436
437                 if (opened_headers > 0) {
438                         gchar *msg;
439
440                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
441                                                opened_headers);
442
443                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
444                         
445                         g_free (msg);
446                         g_object_unref (header_list);
447                         return;
448                 }
449         }
450
451         /* Select message */
452         if (tny_list_get_length(header_list) == 1) {
453                 iter = tny_list_create_iterator (header_list);
454                 header = TNY_HEADER (tny_iterator_get_current (iter));
455                 if (header) {
456                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
457                         g_object_unref (header);
458                 }
459
460                 g_object_unref (iter);
461         }
462         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
463                                            tny_list_get_length(header_list)), desc);
464
465         /* Confirmation dialog */
466         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
467                                                             message);
468         
469
470         if (response == GTK_RESPONSE_OK) {      
471                 ModestWindow *main_window = NULL;
472                 ModestWindowMgr *mgr = NULL;
473                 GtkTreeModel *model = NULL;
474                 GtkTreeSelection *sel = NULL;
475                 GList *sel_list = NULL, *tmp = NULL;
476                 GtkTreeRowReference *next_row_reference = NULL;
477                 GtkTreeRowReference *prev_row_reference = NULL;
478                 GtkTreePath *next_path = NULL;
479                 GtkTreePath *prev_path = NULL;
480                 ModestMailOperation *mail_op = NULL;
481
482                 /* Find last selected row */                    
483                 if (MODEST_IS_MAIN_WINDOW (win)) {
484                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
485                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
486                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
487                         for (tmp=sel_list; tmp; tmp=tmp->next) {
488                                 if (tmp->next == NULL) {
489                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
490                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
491
492                                         gtk_tree_path_prev (prev_path);
493                                         gtk_tree_path_next (next_path);
494
495                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
496                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
497                                 }
498                         }
499                 }
500                 
501                 /* Disable window dimming management */
502                 modest_window_disable_dimming (MODEST_WINDOW(win));
503
504                 /* Remove each header. If it's a view window header_view == NULL */
505                 mail_op = modest_mail_operation_new ((GObject *) win);
506                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
507                                                  mail_op);
508                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
509                 g_object_unref (mail_op);
510                 
511                 /* Enable window dimming management */
512                 if (sel != NULL) {
513                         gtk_tree_selection_unselect_all (sel);
514                 }
515                 modest_window_enable_dimming (MODEST_WINDOW(win));
516                 
517                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
518                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
519                         
520                         /* Get main window */
521                         mgr = modest_runtime_get_window_mgr ();
522                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
523                 } else {                        
524                         /* Move cursor to next row */
525                         main_window = win; 
526
527                         /* Select next or previous row */
528                         if (gtk_tree_row_reference_valid (next_row_reference)) {
529 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
530                                 gtk_tree_selection_select_path (sel, next_path);
531                         }
532                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
533                                 gtk_tree_selection_select_path (sel, prev_path);
534                         }
535
536                         /* Free */
537                         if (next_row_reference != NULL) 
538                                 gtk_tree_row_reference_free (next_row_reference);
539                         if (next_path != NULL) 
540                                 gtk_tree_path_free (next_path);                         
541                         if (prev_row_reference != NULL) 
542                                 gtk_tree_row_reference_free (prev_row_reference);
543                         if (prev_path != NULL) 
544                                 gtk_tree_path_free (prev_path);                         
545                 }
546                 
547                 /* Update toolbar dimming state */
548                 if (main_window)
549                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
550
551                 /* Free */
552                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
553                 g_list_free (sel_list);
554         }
555
556         /* Free*/
557         g_free(message);
558         g_free(desc);
559         g_object_unref (header_list);
560 }
561
562
563
564
565 /* delete either message or folder, based on where we are */
566 void
567 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
568 {
569         g_return_if_fail (MODEST_IS_WINDOW(win));
570         
571         /* Check first if the header view has the focus */
572         if (MODEST_IS_MAIN_WINDOW (win)) {
573                 GtkWidget *w;
574                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
575                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
576                 if (gtk_widget_is_focus (w)) {
577                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
578                         return;
579                 }
580         }
581         modest_ui_actions_on_delete_message (action, win);
582 }
583
584
585
586 void
587 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
588 {       
589         ModestWindowMgr *mgr = NULL;
590         
591 #ifdef MODEST_PLATFORM_MAEMO
592         modest_osso_save_state();
593 #endif /* MODEST_PLATFORM_MAEMO */
594
595         g_debug ("closing down, clearing %d item(s) from operation queue",
596                  modest_mail_operation_queue_num_elements
597                  (modest_runtime_get_mail_operation_queue()));
598
599         /* cancel all outstanding operations */
600         modest_mail_operation_queue_cancel_all 
601                 (modest_runtime_get_mail_operation_queue());
602         
603         g_debug ("queue has been cleared");
604
605
606         /* Check if there are opened editing windows */ 
607         mgr = modest_runtime_get_window_mgr ();
608         modest_window_mgr_close_all_windows (mgr);
609
610         /* note: when modest-tny-account-store is finalized,
611            it will automatically set all network connections
612            to offline */
613
614 /*      gtk_main_quit (); */
615 }
616
617 void
618 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
619 {
620         gboolean ret_value;
621
622         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
623
624 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
625 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
626 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
627 /*              gboolean ret_value; */
628 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
629 /*      } else if (MODEST_IS_WINDOW (win)) { */
630 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
631 /*      } else { */
632 /*              g_return_if_reached (); */
633 /*      } */
634 }
635
636 void
637 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
638 {
639         GtkClipboard *clipboard = NULL;
640         gchar *selection = NULL;
641
642         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
643         selection = gtk_clipboard_wait_for_text (clipboard);
644
645         /* Question: why is the clipboard being used here? 
646          * It doesn't really make a lot of sense. */
647
648         if (selection)
649         {
650                 modest_address_book_add_address (selection);
651                 g_free (selection);
652         }
653 }
654
655 void
656 modest_ui_actions_on_accounts (GtkAction *action, 
657                                ModestWindow *win)
658 {
659         /* This is currently only implemented for Maemo */
660 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
661         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
662                 modest_ui_actions_run_account_setup_wizard (win);
663                 return;
664         } else {
665                 /* Show the list of accounts */
666                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
667                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
668                 
669                 /* The accounts dialog must be modal */
670                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
671                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
672         }
673 #else
674         GtkWidget *dialog, *label;
675         
676         /* Create the widgets */
677         
678         dialog = gtk_dialog_new_with_buttons ("Message",
679                                               GTK_WINDOW(win),
680                                               GTK_DIALOG_DESTROY_WITH_PARENT,
681                                               GTK_STOCK_OK,
682                                               GTK_RESPONSE_NONE,
683                                               NULL);
684         label = gtk_label_new ("Hello World!");
685         
686         /* Ensure that the dialog box is destroyed when the user responds. */
687         
688         g_signal_connect_swapped (dialog, "response", 
689                                   G_CALLBACK (gtk_widget_destroy),
690                                   dialog);
691         
692         /* Add the label, and show everything we've added to the dialog. */
693         
694         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
695                            label);
696         gtk_widget_show_all (dialog);
697 #endif /* MODEST_PLATFORM_MAEMO */
698 }
699
700 static void
701 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
702 {
703         /* Save any changes. */
704         modest_connection_specific_smtp_window_save_server_accounts (
705                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
706         gtk_widget_destroy (GTK_WIDGET (window));
707 }
708
709
710
711 void
712 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
713 {
714         /* This is currently only implemented for Maemo,
715          * because it requires an API (libconic) to detect different connection 
716          * possiblities.
717          */
718 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
719         
720         /* Create the window if necessary: */
721         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
722         modest_connection_specific_smtp_window_fill_with_connections (
723                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
724                 modest_runtime_get_account_mgr());
725
726         /* Show the window: */  
727         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
728         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
729         gtk_widget_show (specific_window);
730     
731         /* Save changes when the window is hidden: */
732         g_signal_connect (specific_window, "hide", 
733                 G_CALLBACK (on_smtp_servers_window_hide), win);
734 #endif /* MODEST_PLATFORM_MAEMO */
735 }
736
737 void
738 modest_ui_actions_compose_msg(ModestWindow *win,
739                               const gchar *to_str,
740                               const gchar *cc_str,
741                               const gchar *bcc_str,
742                               const gchar *subject_str,
743                               const gchar *body_str,
744                               GSList *attachments)
745 {
746         gchar *account_name = NULL;
747         TnyMsg *msg = NULL;
748         TnyAccount *account = NULL;
749         TnyFolder *folder = NULL;
750         gchar *from_str = NULL, *signature = NULL, *body = NULL;
751         gboolean use_signature = FALSE;
752         ModestWindow *msg_win = NULL;
753         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
754         ModestTnyAccountStore *store = modest_runtime_get_account_store();
755
756         if (win) account_name = g_strdup (modest_window_get_active_account (win));
757         if (!account_name) account_name = modest_account_mgr_get_default_account(mgr);
758         if (!account_name) {
759                 g_printerr ("modest: no account found\n");
760                 goto cleanup;
761         }
762         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
763         if (!account) {
764                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
765                 goto cleanup;
766         }
767         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
768         if (!folder) {
769                 g_printerr ("modest: failed to find Drafts folder\n");
770                 goto cleanup;
771         }
772         from_str = modest_account_mgr_get_from_string (mgr, account_name);
773         if (!from_str) {
774                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
775                 goto cleanup;
776         }
777
778         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
779         if (body_str != NULL) {
780                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
781         } else {
782                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
783         }
784
785         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
786         if (!msg) {
787                 g_printerr ("modest: failed to create new msg\n");
788                 goto cleanup;
789         }
790
791         /* Create and register edit window */
792         /* This is destroyed by TODO. */
793         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
794         while (attachments) {
795                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
796                                                        attachments->data);
797                 attachments = g_slist_next(attachments);
798         }
799         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
800
801         if (win) {
802                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
803                                               GTK_WINDOW (win));
804         }
805         gtk_widget_show_all (GTK_WIDGET (msg_win));
806
807 cleanup:
808         g_free (from_str);
809         g_free (signature);
810         g_free (body);
811         g_free (account_name);
812         if (account) g_object_unref (G_OBJECT(account));
813         if (folder) g_object_unref (G_OBJECT(folder));
814         if (msg_win) g_object_unref (G_OBJECT(msg_win));
815         if (msg) g_object_unref (G_OBJECT(msg));
816 }
817
818 void
819 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
820 {
821         /* if there are no accounts yet, just show the wizard */
822         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
823                 if (!modest_ui_actions_run_account_setup_wizard (win)) return;
824         }
825
826         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
827 }
828
829 gboolean 
830 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
831                                        TnyHeader *header,
832                                        TnyMsg *msg)
833 {
834         ModestMailOperationStatus status;
835
836         /* If there is no message or the operation was not successful */
837         status = modest_mail_operation_get_status (mail_op);
838         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
839
840                 /* Remove the header from the preregistered uids */
841                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
842                                                      header);
843
844                 return FALSE;
845         }
846
847         return TRUE;
848 }
849
850 static void
851 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
852 {
853         ModestWindowMgr *mgr = NULL;
854         ModestWindow *parent_win = NULL;
855         ModestWindow *win = NULL;
856         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
857         gchar *account = NULL;
858         TnyFolder *folder;
859         gboolean open_in_editor = FALSE;
860         
861         /* Do nothing if there was any problem with the mail
862            operation. The error will be shown by the error_handler of
863            the mail operation */
864         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
865                 return;
866
867         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
868         folder = tny_header_get_folder (header);
869
870         /* Mark header as read */
871         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
872
873         /* Gets folder type (OUTBOX headers will be opened in edit window */
874         if (modest_tny_folder_is_local_folder (folder)) {
875                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
876                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
877                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
878         }
879
880                 
881         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
882                 TnyTransportAccount *traccount = NULL;
883                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
884                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
885                 if (traccount) {
886                         ModestTnySendQueue *send_queue = NULL;
887                         ModestTnySendQueueStatus status;
888                         char *msg_id;
889                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
890                                                    TNY_ACCOUNT(traccount)));
891                         send_queue = modest_runtime_get_send_queue(traccount);
892                         msg_id = modest_tny_send_queue_get_msg_id (header);
893                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
894                         /* Only open messages in outbox with the editor if they are in Failed state */
895                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
896                                 open_in_editor = TRUE;
897                         }
898                         g_free(msg_id);
899                         g_object_unref(traccount);
900                 } else {
901                         g_warning("Cannot get transport account for message in outbox!!");
902                 }
903         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
904                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
905         }
906
907         /* Get account */
908         if (!account)
909                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
910         if (!account)
911                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
912         
913         if (open_in_editor) {
914                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
915                 const gchar *from_header = NULL;
916
917                 from_header = tny_header_get_from (header);
918
919                 /* we cannot edit without a valid account... */
920                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
921                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
922                                 goto cleanup;
923                 }
924                 
925                 if (from_header) {
926                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
927                         GSList *node = NULL;
928                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
929                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
930                                 
931                                 if (from && (strcmp (from_header, from) == 0)) {
932                                         g_free (account);
933                                         account = g_strdup (node->data);
934                                         g_free (from);
935                                         break;
936                                 }
937                                 g_free (from);
938                         }
939                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
940                         g_slist_free (accounts);
941                 }
942
943                 win = modest_msg_edit_window_new (msg, account, TRUE);
944
945
946                 /* Show banner */
947                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
948
949         } else {
950                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
951                 
952                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
953                         GtkWidget *header_view;
954                         GtkTreeSelection *sel;
955                         GList *sel_list = NULL;
956                         GtkTreeModel *model;
957                         
958                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
959                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
960
961                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
962                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
963
964                         if (sel_list != NULL) {
965                                 GtkTreeRowReference *row_reference;
966
967                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
968                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
969                                 g_list_free (sel_list);
970                                 
971                                 win = modest_msg_view_window_new_with_header_model (
972                                                 msg, account, (const gchar*) uid,
973                                                 model, row_reference);
974                                 gtk_tree_row_reference_free (row_reference);
975                         } else {
976                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
977                         }
978                 } else {
979                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
980                 }
981                 g_free (uid);
982         }
983         
984         /* Register and show new window */
985         if (win != NULL) {
986                 mgr = modest_runtime_get_window_mgr ();
987                 modest_window_mgr_register_window (mgr, win);
988                 g_object_unref (win);
989                 gtk_widget_show_all (GTK_WIDGET(win));
990         }
991
992         /* Update toolbar dimming state */
993         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
994                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
995         }
996
997 cleanup:
998         /* Free */
999         g_free(account);
1000         g_object_unref (parent_win);
1001         g_object_unref (folder);
1002 }
1003
1004
1005 static void
1006 open_msg_error_handler (ModestMailOperation *mail_op,
1007                         gpointer user_data)
1008 {
1009         /* Show the message error */
1010         GObject *win = modest_mail_operation_get_source (mail_op);
1011
1012         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, 
1013                                                 (gchar *) user_data);
1014         if (win)
1015                 g_object_unref (win);
1016 }
1017
1018 void
1019 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1020                                                gpointer user_data)
1021 {
1022         const GError *error;
1023         GObject *win = modest_mail_operation_get_source (mail_op);
1024
1025         error = modest_mail_operation_get_error (mail_op);
1026  
1027         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
1028
1029                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1030                                                         error->message);
1031         } else {
1032                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1033                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
1034         }
1035
1036         if (win)
1037                 g_object_unref (win);
1038 }
1039
1040 /**
1041  * Returns the account a list of headers belongs to. It returns a
1042  * *new* reference so don't forget to unref it
1043  */
1044 static TnyAccount*
1045 get_account_from_header_list (TnyList *headers)
1046 {
1047         TnyAccount *account = NULL;
1048
1049         if (tny_list_get_length (headers) > 0) {
1050                 TnyIterator *iter = tny_list_create_iterator (headers);
1051                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1052                 TnyFolder *folder = tny_header_get_folder (header);
1053                 account = tny_folder_get_account (folder);
1054                 g_object_unref (folder);
1055                 g_object_unref (header);
1056                 g_object_unref (iter);
1057         }
1058         return account;
1059 }
1060
1061 /*
1062  * This function is used by both modest_ui_actions_on_open and
1063  * modest_ui_actions_on_header_activated. This way we always do the
1064  * same when trying to open messages.
1065  */
1066 static void
1067 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
1068 {
1069         ModestWindowMgr *mgr = NULL;
1070         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1071         ModestMailOperation *mail_op = NULL;
1072         TnyList *not_opened_headers = NULL;
1073         TnyHeaderFlags flags = 0;
1074         TnyAccount *account;
1075                 
1076         g_return_if_fail (headers != NULL);
1077
1078         /* Check that only one message is selected for opening */
1079         if (tny_list_get_length (headers) != 1) {
1080                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1081                                                         _("mcen_ib_select_one_message"));
1082                 return;
1083         }
1084
1085         mgr = modest_runtime_get_window_mgr ();
1086         iter = tny_list_create_iterator (headers);
1087
1088         /* Get the account */
1089         account = get_account_from_header_list (headers);
1090         
1091         /* Look if we already have a message view for each header. If
1092            true, then remove the header from the list of headers to
1093            open */
1094         not_opened_headers = tny_simple_list_new ();
1095         while (!tny_iterator_is_done (iter)) {
1096
1097                 ModestWindow *window = NULL;
1098                 TnyHeader *header = NULL;
1099                 gboolean found = FALSE;
1100                 
1101                 header = TNY_HEADER (tny_iterator_get_current (iter));
1102                 if (header)
1103                         flags = tny_header_get_flags (header);
1104
1105                 window = NULL;
1106                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1107                 
1108                 /* Do not open again the message and present the
1109                    window to the user */
1110                 if (found) {
1111                         if (window)
1112                                 gtk_window_present (GTK_WINDOW (window));
1113                         else
1114                                 /* the header has been registered already, we don't do
1115                                  * anything but wait for the window to come up*/
1116                                 g_debug ("header %p already registered, waiting for window", header);
1117                 } else {
1118                         tny_list_append (not_opened_headers, G_OBJECT (header));
1119                 }
1120
1121                 if (header)
1122                         g_object_unref (header);
1123
1124                 tny_iterator_next (iter);
1125         }
1126         g_object_unref (iter);
1127         iter = NULL;
1128
1129         /* Open each message */
1130         if (tny_list_get_length (not_opened_headers) == 0)
1131                 goto cleanup;
1132         
1133         /* If some messages would have to be downloaded, ask the user to 
1134          * make a connection. It's generally easier to do this here (in the mainloop) 
1135          * than later in a thread:
1136          */
1137         if (tny_list_get_length (not_opened_headers) > 0) {
1138                 TnyIterator *iter;
1139                 gboolean found = FALSE;
1140
1141                 iter = tny_list_create_iterator (not_opened_headers);
1142                 while (!tny_iterator_is_done (iter) && !found) {
1143                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1144                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1145                                 found = TRUE;
1146                         else
1147                                 tny_iterator_next (iter);
1148
1149                         g_object_unref (header);
1150                 }
1151                 g_object_unref (iter);
1152
1153                 /* Ask the user if there are any uncached messages */
1154                 if (found && !connect_to_get_msg (win, 
1155                                                   header_list_count_uncached_msgs (not_opened_headers), 
1156                                                   account))
1157                         goto cleanup;
1158         }
1159         
1160         /* Register the headers before actually creating the windows: */
1161         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1162         while (!tny_iterator_is_done (iter_not_opened)) {
1163                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1164                 if (header) {
1165                         modest_window_mgr_register_header (mgr, header, NULL);
1166                         g_object_unref (header);
1167                 }               
1168                 tny_iterator_next (iter_not_opened);
1169         }
1170         g_object_unref (iter_not_opened);
1171         iter_not_opened = NULL;
1172
1173         /* Create the mail operation */
1174         if (tny_list_get_length (not_opened_headers) > 1) {
1175                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win), 
1176                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1177                                                                          NULL, NULL);
1178                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1179                 
1180                 modest_mail_operation_get_msgs_full (mail_op, 
1181                                                      not_opened_headers, 
1182                                                      open_msg_cb, 
1183                                                      NULL, 
1184                                                      NULL);
1185         } else {
1186                 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1187                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1188                 const gchar *proto_name;
1189                 gchar *error_msg;
1190                 ModestTransportStoreProtocol proto;
1191
1192                 /* Get the error message depending on the protocol */
1193                 proto_name = tny_account_get_proto (account);
1194                 if (proto_name != NULL) {
1195                         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1196                 } else {
1197                         proto = MODEST_PROTOCOL_STORE_MAILDIR;
1198                 }
1199                 
1200                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1201                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1202                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1203                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1204                                                      tny_header_get_subject (header));
1205                 } else {
1206                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1207                 }
1208
1209                 /* Create and call the mail operation */
1210                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win), 
1211                                                                          open_msg_error_handler, 
1212                                                                          error_msg,
1213                                                                          g_free);
1214                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1215
1216                 modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1217
1218                 g_object_unref (header);
1219                 g_object_unref (iter);
1220         }
1221         g_object_unref (mail_op);
1222
1223 cleanup:
1224         /* Clean */
1225         if (account)
1226                 g_object_unref (account);
1227         if (not_opened_headers)
1228                 g_object_unref (not_opened_headers);
1229 }
1230
1231 void
1232 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1233 {
1234         TnyList *headers;
1235
1236         /* Get headers */
1237         headers = get_selected_headers (win);
1238         if (!headers)
1239                 return;
1240
1241         /* Open them */
1242         _modest_ui_actions_open (headers, win);
1243
1244         g_object_unref(headers);
1245 }
1246
1247
1248 static void
1249 free_reply_forward_helper (gpointer data)
1250 {
1251         ReplyForwardHelper *helper;
1252
1253         helper = (ReplyForwardHelper *) data;
1254         g_free (helper->account_name);
1255         g_slice_free (ReplyForwardHelper, helper);
1256 }
1257
1258 static void
1259 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1260                   gpointer user_data)
1261 {
1262         TnyMsg *new_msg;
1263         ReplyForwardHelper *rf_helper;
1264         ModestWindow *msg_win = NULL;
1265         ModestEditType edit_type;
1266         gchar *from = NULL;
1267         TnyAccount *account = NULL;
1268         ModestWindowMgr *mgr = NULL;
1269         gchar *signature = NULL;
1270         gboolean use_signature;
1271
1272         /* If there was any error. The mail operation could be NULL,
1273            this means that we already have the message downloaded and
1274            that we didn't do a mail operation to retrieve it */
1275         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1276                 return;
1277                         
1278         g_return_if_fail (user_data != NULL);
1279         rf_helper = (ReplyForwardHelper *) user_data;
1280
1281         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1282                                                    rf_helper->account_name);
1283         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1284                                                       rf_helper->account_name, 
1285                                                       &use_signature);
1286
1287         /* Create reply mail */
1288         switch (rf_helper->action) {
1289         case ACTION_REPLY:
1290                 new_msg = 
1291                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1292                                                          rf_helper->reply_forward_type,
1293                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1294                 break;
1295         case ACTION_REPLY_TO_ALL:
1296                 new_msg = 
1297                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1298                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1299                 edit_type = MODEST_EDIT_TYPE_REPLY;
1300                 break;
1301         case ACTION_FORWARD:
1302                 new_msg = 
1303                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1304                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1305                 break;
1306         default:
1307                 g_return_if_reached ();
1308                 return;
1309         }
1310
1311         g_free (signature);
1312
1313         if (!new_msg) {
1314                 g_printerr ("modest: failed to create message\n");
1315                 goto cleanup;
1316         }
1317
1318         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1319                                                                        rf_helper->account_name,
1320                                                                        TNY_ACCOUNT_TYPE_STORE);
1321         if (!account) {
1322                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1323                 goto cleanup;
1324         }
1325
1326         /* Create and register the windows */
1327         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1328         mgr = modest_runtime_get_window_mgr ();
1329         modest_window_mgr_register_window (mgr, msg_win);
1330
1331         if (rf_helper->parent_window != NULL) {
1332                 gdouble parent_zoom;
1333
1334                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1335                 modest_window_set_zoom (msg_win, parent_zoom);
1336         }
1337
1338         /* Show edit window */
1339         gtk_widget_show_all (GTK_WIDGET (msg_win));
1340
1341 cleanup:
1342         if (msg_win)
1343                 g_object_unref (msg_win);
1344         if (new_msg)
1345                 g_object_unref (G_OBJECT (new_msg));
1346         if (account)
1347                 g_object_unref (G_OBJECT (account));
1348 /*      g_object_unref (msg); */
1349         free_reply_forward_helper (rf_helper);
1350 }
1351
1352 /* Checks a list of headers. If any of them are not currently
1353  * downloaded (CACHED) then returns TRUE else returns FALSE.
1354  */
1355 static gint
1356 header_list_count_uncached_msgs (TnyList *header_list)
1357 {
1358         TnyIterator *iter;
1359         gint uncached_messages = 0;
1360
1361         iter = tny_list_create_iterator (header_list);
1362         while (!tny_iterator_is_done (iter)) {
1363                 TnyHeader *header;
1364
1365                 header = TNY_HEADER (tny_iterator_get_current (iter));
1366                 if (header) {
1367                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1368                                 uncached_messages ++;
1369                         g_object_unref (header);
1370                 }
1371
1372                 tny_iterator_next (iter);
1373         }
1374         g_object_unref (iter);
1375
1376         return uncached_messages;
1377 }
1378
1379 /* Returns FALSE if the user does not want to download the
1380  * messages. Returns TRUE if the user allowed the download.
1381  */
1382 static gboolean
1383 connect_to_get_msg (ModestWindow *win,
1384                     gint num_of_uncached_msgs,
1385                     TnyAccount *account)
1386 {
1387         GtkResponseType response;
1388
1389         /* Allways download if we are online. */
1390         if (tny_device_is_online (modest_runtime_get_device ()))
1391                 return TRUE;
1392
1393         /* If offline, then ask for user permission to download the messages */
1394         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1395                         ngettext("mcen_nc_get_msg",
1396                         "mcen_nc_get_msgs",
1397                         num_of_uncached_msgs));
1398
1399         if (response == GTK_RESPONSE_CANCEL)
1400                 return FALSE;
1401
1402         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1403 }
1404
1405 /*
1406  * Common code for the reply and forward actions
1407  */
1408 static void
1409 reply_forward (ReplyForwardAction action, ModestWindow *win)
1410 {
1411         ModestMailOperation *mail_op = NULL;
1412         TnyList *header_list = NULL;
1413         ReplyForwardHelper *rf_helper = NULL;
1414         guint reply_forward_type;
1415         gboolean continue_download = TRUE;
1416         gboolean do_retrieve = TRUE;
1417         
1418         g_return_if_fail (MODEST_IS_WINDOW(win));
1419
1420         /* we need an account when editing */
1421         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1422                 if (!modest_ui_actions_run_account_setup_wizard (win))
1423                         return;
1424         }
1425         
1426         header_list = get_selected_headers (win);
1427         if (!header_list)
1428                 return;
1429
1430         reply_forward_type = 
1431                 modest_conf_get_int (modest_runtime_get_conf (),
1432                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1433                                      NULL);
1434
1435         /* check if we need to download msg before asking about it */
1436         do_retrieve = (action == ACTION_FORWARD) ||
1437                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1438
1439         if (do_retrieve){
1440                 gint num_of_unc_msgs;
1441
1442                 /* check that the messages have been previously downloaded */
1443                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1444                 /* If there are any uncached message ask the user
1445                  * whether he/she wants to download them. */
1446                 if (num_of_unc_msgs) {
1447                         TnyAccount *account = get_account_from_header_list (header_list);
1448                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1449                         g_object_unref (account);
1450                 }
1451         }
1452
1453         if (!continue_download) {
1454                 g_object_unref (header_list);
1455                 return;
1456         }
1457         
1458         /* We assume that we can only select messages of the
1459            same folder and that we reply all of them from the
1460            same account. In fact the interface currently only
1461            allows single selection */
1462         
1463         /* Fill helpers */
1464         rf_helper = g_slice_new0 (ReplyForwardHelper);
1465         rf_helper->reply_forward_type = reply_forward_type;
1466         rf_helper->action = action;
1467         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1468         
1469         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1470                 rf_helper->parent_window = GTK_WIDGET (win);
1471         if (!rf_helper->account_name)
1472                 rf_helper->account_name =
1473                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1474
1475         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1476                 TnyMsg *msg;
1477                 TnyHeader *header;
1478                 /* Get header and message. Do not free them here, the
1479                    reply_forward_cb must do it */
1480                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1481                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1482                 if (!msg || !header) {
1483                         if (msg)
1484                                 g_object_unref (msg);
1485                         g_printerr ("modest: no message found\n");
1486                         return;
1487                 } else {
1488                         reply_forward_cb (NULL, header, msg, rf_helper);
1489                 }
1490                 if (header)
1491                         g_object_unref (header);
1492         } else {
1493                 TnyHeader *header;
1494                 TnyIterator *iter;
1495
1496                 /* Only reply/forward to one message */
1497                 iter = tny_list_create_iterator (header_list);
1498                 header = TNY_HEADER (tny_iterator_get_current (iter));
1499                 g_object_unref (iter);
1500
1501                 if (header) {
1502                         /* Retrieve messages */
1503                         if (do_retrieve) {
1504                                 mail_op = 
1505                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1506                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1507                                                                                        NULL, NULL);
1508                                 modest_mail_operation_queue_add (
1509                                         modest_runtime_get_mail_operation_queue (), mail_op);
1510                                 
1511                                 modest_mail_operation_get_msg (mail_op,
1512                                                                header,
1513                                                                reply_forward_cb,
1514                                                                rf_helper);
1515                                 /* Clean */
1516                                 g_object_unref(mail_op);
1517                         } else {
1518                                 /* we put a ref here to prevent double unref as the reply
1519                                  * forward callback unrefs the header at its end */
1520                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1521                         }
1522
1523
1524                         g_object_unref (header);
1525                 }
1526
1527         }
1528
1529         /* Free */
1530         g_object_unref (header_list);
1531 }
1532
1533 void
1534 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1535 {
1536         g_return_if_fail (MODEST_IS_WINDOW(win));
1537
1538         reply_forward (ACTION_REPLY, win);
1539 }
1540
1541 void
1542 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1543 {
1544         g_return_if_fail (MODEST_IS_WINDOW(win));
1545
1546         reply_forward (ACTION_FORWARD, win);
1547 }
1548
1549 void
1550 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1551 {
1552         g_return_if_fail (MODEST_IS_WINDOW(win));
1553
1554         reply_forward (ACTION_REPLY_TO_ALL, win);
1555 }
1556
1557 void 
1558 modest_ui_actions_on_next (GtkAction *action, 
1559                            ModestWindow *window)
1560 {
1561         if (MODEST_IS_MAIN_WINDOW (window)) {
1562                 GtkWidget *header_view;
1563
1564                 header_view = modest_main_window_get_child_widget (
1565                                 MODEST_MAIN_WINDOW(window),
1566                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1567                 if (!header_view)
1568                         return;
1569         
1570                 modest_header_view_select_next (
1571                                 MODEST_HEADER_VIEW(header_view)); 
1572         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1573                 modest_msg_view_window_select_next_message (
1574                                 MODEST_MSG_VIEW_WINDOW (window));
1575         } else {
1576                 g_return_if_reached ();
1577         }
1578 }
1579
1580 void 
1581 modest_ui_actions_on_prev (GtkAction *action, 
1582                            ModestWindow *window)
1583 {
1584         g_return_if_fail (MODEST_IS_WINDOW(window));
1585
1586         if (MODEST_IS_MAIN_WINDOW (window)) {
1587                 GtkWidget *header_view;
1588                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1589                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1590                 if (!header_view)
1591                         return;
1592                 
1593                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1594         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1595                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1596         } else {
1597                 g_return_if_reached ();
1598         }
1599 }
1600
1601 void 
1602 modest_ui_actions_on_sort (GtkAction *action, 
1603                            ModestWindow *window)
1604 {
1605         g_return_if_fail (MODEST_IS_WINDOW(window));
1606
1607         if (MODEST_IS_MAIN_WINDOW (window)) {
1608                 GtkWidget *header_view;
1609                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1610                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1611                 if (!header_view) {
1612                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1613
1614                         return;
1615                 }
1616
1617                 /* Show sorting dialog */
1618                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1619         }
1620 }
1621
1622 static void
1623 new_messages_arrived (ModestMailOperation *self, 
1624                       TnyList *new_headers,
1625                       gpointer user_data)
1626 {
1627         GObject *source;
1628
1629         source = modest_mail_operation_get_source (self);
1630
1631         /* Notify new messages have been downloaded. Do not notify if
1632            the send&receive was invoked by the user, i.e, if the mail
1633            operation has a source (the main window) */
1634         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0) && !source)
1635                 modest_platform_on_new_headers_received (new_headers);
1636
1637         if (source)
1638                 g_object_unref (source);
1639 }
1640
1641 /*
1642  * This function performs the send & receive required actions. The
1643  * window is used to create the mail operation. Typically it should
1644  * always be the main window, but we pass it as argument in order to
1645  * be more flexible.
1646  */
1647 void
1648 modest_ui_actions_do_send_receive (const gchar *account_name, 
1649                                    ModestWindow *win)
1650 {
1651         gchar *acc_name = NULL;
1652         ModestMailOperation *mail_op;
1653         TnyAccount *store_account = NULL;
1654
1655         /* If no account name was provided then get the current account, and if
1656            there is no current account then pick the default one: */
1657         if (!account_name) {
1658                 if (win)
1659                         acc_name = g_strdup (modest_window_get_active_account (win));
1660                 if (!acc_name)
1661                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1662                 if (!acc_name) {
1663                         g_printerr ("modest: cannot get default account\n");
1664                         return;
1665                 }
1666         } else {
1667                 acc_name = g_strdup (account_name);
1668         }
1669
1670         /* Ensure that we have a connection available */
1671         store_account =
1672                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1673                                                              acc_name,
1674                                                              TNY_ACCOUNT_TYPE_STORE);
1675
1676         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1677                 g_object_unref (store_account);
1678                 return;
1679         }
1680         g_object_unref (store_account);
1681
1682         /* Set send/receive operation in progress */    
1683         if (win && MODEST_IS_MAIN_WINDOW (win))
1684                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1685         
1686         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
1687                                                                  modest_ui_actions_send_receive_error_handler,
1688                                                                  NULL, NULL);
1689
1690         if (win && MODEST_IS_MAIN_WINDOW (win))
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_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2613                            error->code, error->message);
2614                 return;
2615         }
2616
2617         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2618 }
2619
2620 void 
2621 modest_ui_actions_on_rename_folder (GtkAction *action,
2622                                      ModestMainWindow *main_window)
2623 {
2624         TnyFolderStore *folder;
2625         GtkWidget *folder_view;
2626         GtkWidget *header_view; 
2627
2628         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2629
2630         folder_view = modest_main_window_get_child_widget (main_window,
2631                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2632         if (!folder_view)
2633                 return;
2634
2635         header_view = modest_main_window_get_child_widget (main_window,
2636                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2637         
2638         if (!header_view)
2639                 return;
2640
2641         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2642
2643         if (!folder)
2644                 return;
2645
2646         if (TNY_IS_FOLDER (folder)) {
2647                 gchar *folder_name;
2648                 gint response;
2649                 const gchar *current_name;
2650                 TnyFolderStore *parent;
2651                 gboolean do_rename = TRUE;
2652
2653                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2654                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2655                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2656                                                                      parent, current_name, 
2657                                                                      &folder_name);
2658                 g_object_unref (parent);
2659
2660                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2661                         do_rename = FALSE;
2662                 } else if (modest_platform_is_network_folderstore(folder) &&
2663                            !tny_device_is_online (modest_runtime_get_device())) {
2664                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2665                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2666                         g_object_unref(account);
2667                 }
2668
2669                 if (do_rename) {
2670                         ModestMailOperation *mail_op;
2671                         GtkTreeSelection *sel = NULL;
2672
2673                         mail_op = 
2674                                 modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2675                                                                                modest_ui_actions_rename_folder_error_handler,
2676                                                                                main_window, NULL);
2677
2678                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2679                                                          mail_op);
2680
2681                         /* Clear the headers view */
2682                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2683                         gtk_tree_selection_unselect_all (sel);
2684
2685                         /* Select *after* the changes */
2686                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2687                                                           TNY_FOLDER(folder), TRUE);
2688
2689                         /* Actually rename the folder */
2690                         modest_mail_operation_rename_folder (mail_op,
2691                                                              TNY_FOLDER (folder),
2692                                                              (const gchar *) folder_name);
2693
2694                         g_object_unref (mail_op);
2695                         g_free (folder_name);
2696                 }
2697         }
2698         g_object_unref (folder);
2699 }
2700
2701 static void
2702 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2703                                                gpointer user_data)
2704 {
2705         GObject *win = modest_mail_operation_get_source (mail_op);
2706
2707         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2708                                                 _("mail_in_ui_folder_delete_error"));
2709         g_object_unref (win);
2710 }
2711
2712 static gboolean
2713 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2714 {
2715         TnyFolderStore *folder;
2716         GtkWidget *folder_view;
2717         gint response;
2718         gchar *message;
2719         gboolean do_delete = TRUE;
2720
2721         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2722
2723         folder_view = modest_main_window_get_child_widget (main_window,
2724                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2725         if (!folder_view)
2726                 return FALSE;
2727
2728         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2729
2730         /* Show an error if it's an account */
2731         if (!TNY_IS_FOLDER (folder)) {
2732                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2733                                                         _("mail_in_ui_folder_delete_error"));
2734                 g_object_unref (G_OBJECT (folder));
2735                 return FALSE;
2736         }
2737
2738         /* Ask the user */      
2739         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2740                                     tny_folder_get_name (TNY_FOLDER (folder)));
2741         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2742                                                             (const gchar *) message);
2743         g_free (message);
2744
2745         if (response != GTK_RESPONSE_OK) {
2746                 do_delete = FALSE;
2747         } else if (modest_platform_is_network_folderstore(folder) &&
2748                    !tny_device_is_online (modest_runtime_get_device())) {
2749                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2750                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2751                 g_object_unref(account);
2752         }
2753
2754         if (do_delete) {
2755                 ModestMailOperation *mail_op;
2756                 GtkTreeSelection *sel;
2757
2758                 /* Unselect the folder before deleting it to free the headers */
2759                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2760                 gtk_tree_selection_unselect_all (sel);
2761
2762                 /* Create the mail operation */
2763                 mail_op =
2764                         modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2765                                                                        modest_ui_actions_delete_folder_error_handler,
2766                                                                        NULL, NULL);
2767
2768                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2769                                                  mail_op);
2770                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2771                 g_object_unref (G_OBJECT (mail_op));
2772         }
2773
2774         g_object_unref (G_OBJECT (folder));
2775
2776         return do_delete;
2777 }
2778
2779 void 
2780 modest_ui_actions_on_delete_folder (GtkAction *action,
2781                                      ModestMainWindow *main_window)
2782 {
2783         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2784
2785         delete_folder (main_window, FALSE);
2786 }
2787
2788 void 
2789 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2790 {
2791         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2792         
2793         delete_folder (main_window, TRUE);
2794 }
2795
2796
2797 static void
2798 show_error (GtkWidget *parent_widget, const gchar* text)
2799 {
2800         hildon_banner_show_information(parent_widget, NULL, text);
2801         
2802 #if 0
2803         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2804         /*
2805           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2806           (GtkDialogFlags)0,
2807           GTK_MESSAGE_ERROR,
2808           GTK_BUTTONS_OK,
2809           text ));
2810         */
2811                  
2812         gtk_dialog_run (dialog);
2813         gtk_widget_destroy (GTK_WIDGET (dialog));
2814 #endif
2815 }
2816
2817 void
2818 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2819                                          const gchar* server_account_name,
2820                                          gchar **username,
2821                                          gchar **password, 
2822                                          gboolean *cancel, 
2823                                          gboolean *remember,
2824                                          ModestMainWindow *main_window)
2825 {
2826         g_return_if_fail(server_account_name);
2827         
2828         /* Initalize output parameters: */
2829         if (cancel)
2830                 *cancel = FALSE;
2831                 
2832         if (remember)
2833                 *remember = TRUE;
2834                 
2835 #ifdef MODEST_PLATFORM_MAEMO
2836         /* Maemo uses a different (awkward) button order,
2837          * It should probably just use gtk_alternative_dialog_button_order ().
2838          */
2839         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2840                                               NULL,
2841                                               GTK_DIALOG_MODAL,
2842                                               _("mcen_bd_dialog_ok"),
2843                                               GTK_RESPONSE_ACCEPT,
2844                                               _("mcen_bd_dialog_cancel"),
2845                                               GTK_RESPONSE_REJECT,
2846                                               NULL);
2847 #else
2848         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2849                                               NULL,
2850                                               GTK_DIALOG_MODAL,
2851                                               GTK_STOCK_CANCEL,
2852                                               GTK_RESPONSE_REJECT,
2853                                               GTK_STOCK_OK,
2854                                               GTK_RESPONSE_ACCEPT,
2855                                               NULL);
2856 #endif /* MODEST_PLATFORM_MAEMO */
2857
2858         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2859         
2860         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2861                 modest_runtime_get_account_mgr(), server_account_name);
2862         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2863                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2864                 if (cancel)
2865                         *cancel = TRUE;
2866                 return;
2867         }
2868         
2869         /* This causes a warning because the logical ID has no %s in it, 
2870          * though the translation does, but there is not much we can do about that: */
2871         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2872         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2873                             FALSE, FALSE, 0);
2874         g_free (txt);
2875         g_free (server_name);
2876         server_name = NULL;
2877
2878         /* username: */
2879         gchar *initial_username = modest_account_mgr_get_server_account_username (
2880                 modest_runtime_get_account_mgr(), server_account_name);
2881         
2882         GtkWidget *entry_username = gtk_entry_new ();
2883         if (initial_username)
2884                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2885         /* Dim this if a connection has ever succeeded with this username,
2886          * as per the UI spec: */
2887         const gboolean username_known = 
2888                 modest_account_mgr_get_server_account_username_has_succeeded(
2889                         modest_runtime_get_account_mgr(), server_account_name);
2890         gtk_widget_set_sensitive (entry_username, !username_known);
2891         
2892 #ifdef MODEST_PLATFORM_MAEMO
2893         /* Auto-capitalization is the default, so let's turn it off: */
2894         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2895         
2896         /* Create a size group to be used by all captions.
2897          * Note that HildonCaption does not create a default size group if we do not specify one.
2898          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2899         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2900         
2901         GtkWidget *caption = hildon_caption_new (sizegroup, 
2902                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2903         gtk_widget_show (entry_username);
2904         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2905                 FALSE, FALSE, MODEST_MARGIN_HALF);
2906         gtk_widget_show (caption);
2907 #else 
2908         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2909                             TRUE, FALSE, 0);
2910 #endif /* MODEST_PLATFORM_MAEMO */      
2911                             
2912         /* password: */
2913         GtkWidget *entry_password = gtk_entry_new ();
2914         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2915         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2916         
2917 #ifdef MODEST_PLATFORM_MAEMO
2918         /* Auto-capitalization is the default, so let's turn it off: */
2919         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2920                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2921         
2922         caption = hildon_caption_new (sizegroup, 
2923                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2924         gtk_widget_show (entry_password);
2925         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2926                 FALSE, FALSE, MODEST_MARGIN_HALF);
2927         gtk_widget_show (caption);
2928         g_object_unref (sizegroup);
2929 #else 
2930         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2931                             TRUE, FALSE, 0);
2932 #endif /* MODEST_PLATFORM_MAEMO */      
2933
2934         if (initial_username != NULL)
2935                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2936                                 
2937 /* This is not in the Maemo UI spec:
2938         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2939         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2940                             TRUE, FALSE, 0);
2941 */
2942
2943         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2944         
2945         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2946                 if (username) {
2947                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2948                         
2949                         modest_account_mgr_set_server_account_username (
2950                                  modest_runtime_get_account_mgr(), server_account_name, 
2951                                  *username);
2952                                  
2953                         const gboolean username_was_changed = 
2954                                 (strcmp (*username, initial_username) != 0);
2955                         if (username_was_changed) {
2956                                 g_warning ("%s: tinymail does not yet support changing the "
2957                                         "username in the get_password() callback.\n", __FUNCTION__);
2958                         }
2959                 }
2960                         
2961                 if (password) {
2962                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2963                         
2964                         /* We do not save the password in the configuration, 
2965                          * because this function is only called for passwords that should 
2966                          * not be remembered:
2967                         modest_server_account_set_password (
2968                                  modest_runtime_get_account_mgr(), server_account_name, 
2969                                  *password);
2970                         */
2971                 }
2972                 
2973                 if (cancel)
2974                         *cancel   = FALSE;
2975                         
2976         } else {
2977                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2978                 
2979                 if (username)
2980                         *username = NULL;
2981                         
2982                 if (password)
2983                         *password = NULL;
2984                         
2985                 if (cancel)
2986                         *cancel   = TRUE;
2987         }
2988
2989 /* This is not in the Maemo UI spec:
2990         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2991                 *remember = TRUE;
2992         else
2993                 *remember = FALSE;
2994 */
2995
2996         gtk_widget_destroy (dialog);
2997         
2998         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2999 }
3000
3001 void
3002 modest_ui_actions_on_cut (GtkAction *action,
3003                           ModestWindow *window)
3004 {
3005         GtkWidget *focused_widget;
3006         GtkClipboard *clipboard;
3007
3008         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3009         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3010         if (GTK_IS_EDITABLE (focused_widget)) {
3011                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3012                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3013                 gtk_clipboard_store (clipboard);
3014         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3015                 GtkTextBuffer *buffer;
3016
3017                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3018                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3019                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3020                 gtk_clipboard_store (clipboard);
3021         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3022                 TnyList *header_list = modest_header_view_get_selected_headers (
3023                                 MODEST_HEADER_VIEW (focused_widget));
3024                 gboolean continue_download = FALSE;
3025                 gint num_of_unc_msgs;
3026
3027                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3028
3029                 if (num_of_unc_msgs) {
3030                         TnyAccount *account = get_account_from_header_list (header_list);
3031                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3032                         g_object_unref (account);
3033                 }
3034
3035                 if (num_of_unc_msgs == 0 || continue_download) {
3036 /*                      modest_platform_information_banner (
3037                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3038                         modest_header_view_cut_selection (
3039                                         MODEST_HEADER_VIEW (focused_widget));
3040                 }
3041
3042                 g_object_unref (header_list);
3043         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3044                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3045         }
3046 }
3047
3048 void
3049 modest_ui_actions_on_copy (GtkAction *action,
3050                            ModestWindow *window)
3051 {
3052         GtkClipboard *clipboard;
3053         GtkWidget *focused_widget;
3054         gboolean copied = TRUE;
3055
3056         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3057         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3058
3059         if (GTK_IS_LABEL (focused_widget)) {
3060                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3061                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3062                 gtk_clipboard_store (clipboard);
3063         } else if (GTK_IS_EDITABLE (focused_widget)) {
3064                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3065                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3066                 gtk_clipboard_store (clipboard);
3067         } else if (GTK_IS_HTML (focused_widget)) {
3068                 gtk_html_copy (GTK_HTML (focused_widget));
3069                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3070                 gtk_clipboard_store (clipboard);
3071         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3072                 GtkTextBuffer *buffer;
3073                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3074                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3075                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3076                 gtk_clipboard_store (clipboard);
3077         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3078                 TnyList *header_list = modest_header_view_get_selected_headers (
3079                                 MODEST_HEADER_VIEW (focused_widget));
3080                 gboolean continue_download = FALSE;
3081                 gint num_of_unc_msgs;
3082
3083                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3084
3085                 if (num_of_unc_msgs) {
3086                         TnyAccount *account = get_account_from_header_list (header_list);
3087                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3088                         g_object_unref (account);
3089                 }
3090
3091                 if (num_of_unc_msgs == 0 || continue_download) {
3092                         modest_platform_information_banner (
3093                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3094                         modest_header_view_copy_selection (
3095                                         MODEST_HEADER_VIEW (focused_widget));
3096                 } else
3097                         copied = FALSE;
3098
3099                 g_object_unref (header_list);
3100
3101         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3102                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3103         }
3104
3105         /* Show information banner if there was a copy to clipboard */
3106         if(copied)
3107                 modest_platform_information_banner (
3108                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3109 }
3110
3111 void
3112 modest_ui_actions_on_undo (GtkAction *action,
3113                            ModestWindow *window)
3114 {
3115         ModestEmailClipboard *clipboard = NULL;
3116
3117         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3118                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3119         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3120                 /* Clear clipboard source */
3121                 clipboard = modest_runtime_get_email_clipboard ();
3122                 modest_email_clipboard_clear (clipboard);               
3123         }
3124         else {
3125                 g_return_if_reached ();
3126         }
3127 }
3128
3129 void
3130 modest_ui_actions_on_redo (GtkAction *action,
3131                            ModestWindow *window)
3132 {
3133         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3134                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3135         }
3136         else {
3137                 g_return_if_reached ();
3138         }
3139 }
3140
3141
3142 static void
3143 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3144 {
3145         /* destroy information note */
3146         gtk_widget_destroy (GTK_WIDGET(user_data));
3147 }
3148
3149
3150 static void
3151 paste_as_attachment_free (gpointer data)
3152 {
3153         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3154
3155         gtk_widget_destroy (helper->banner);
3156         g_object_unref (helper->banner);
3157         g_free (helper);
3158 }
3159
3160 static void
3161 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3162                             TnyHeader *header,
3163                             TnyMsg *msg,
3164                             gpointer userdata)
3165 {
3166         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3167         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3168
3169         if (msg == NULL)
3170                 return;
3171
3172         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3173         
3174 }
3175
3176 void
3177 modest_ui_actions_on_paste (GtkAction *action,
3178                             ModestWindow *window)
3179 {
3180         GtkWidget *focused_widget = NULL;
3181         GtkWidget *inf_note = NULL;
3182         ModestMailOperation *mail_op = NULL;
3183
3184         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3185         if (GTK_IS_EDITABLE (focused_widget)) {
3186                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3187         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3188                 ModestEmailClipboard *e_clipboard = NULL;
3189                 e_clipboard = modest_runtime_get_email_clipboard ();
3190                 if (modest_email_clipboard_cleared (e_clipboard)) {
3191                         GtkTextBuffer *buffer;
3192                         GtkClipboard *clipboard;
3193
3194                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3195                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3196                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3197                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3198                         ModestMailOperation *mail_op;
3199                         TnyFolder *src_folder;
3200                         TnyList *data;
3201                         gboolean delete;
3202                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3203                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3204                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3205                                                                            _CS("ckct_nw_pasting"));
3206                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3207                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3208                         if (helper->banner != NULL) {
3209                                 g_object_ref (G_OBJECT (helper->banner));
3210                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3211                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3212                         }
3213
3214                         if (data != NULL) {
3215                                 modest_mail_operation_get_msgs_full (mail_op, 
3216                                                                      data,
3217                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3218                                                                      helper,
3219                                                                      paste_as_attachment_free);
3220                         }
3221                 }
3222         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3223                 ModestEmailClipboard *clipboard = NULL;
3224                 TnyFolder *src_folder = NULL;
3225                 TnyFolderStore *folder_store = NULL;
3226                 TnyList *data = NULL;           
3227                 gboolean delete = FALSE;
3228                 
3229                 /* Check clipboard source */
3230                 clipboard = modest_runtime_get_email_clipboard ();
3231                 if (modest_email_clipboard_cleared (clipboard)) 
3232                         return;
3233                 
3234                 /* Get elements to paste */
3235                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3236
3237                 /* Create a new mail operation */
3238                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3239                 
3240                 /* Get destination folder */
3241                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3242
3243                 /* transfer messages  */
3244                 if (data != NULL) {
3245                         gint response = 0;
3246
3247                         /* Ask for user confirmation */
3248                         response = 
3249                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3250                                                                              TNY_FOLDER (folder_store), 
3251                                                                              delete,
3252                                                                              data);
3253                         
3254                         if (response == GTK_RESPONSE_OK) {
3255                                 /* Launch notification */
3256                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3257                                                                              _CS("ckct_nw_pasting"));
3258                                 if (inf_note != NULL)  {
3259                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3260                                         gtk_widget_show (GTK_WIDGET(inf_note));
3261                                 }
3262
3263                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3264                                 modest_mail_operation_xfer_msgs (mail_op, 
3265                                                                  data,
3266                                                                  TNY_FOLDER (folder_store),
3267                                                                  delete,
3268                                                                  destroy_information_note,
3269                                                                  inf_note);                             
3270                         } else {
3271                                 g_object_unref (mail_op);
3272                         }
3273                         
3274                 } else if (src_folder != NULL) {                        
3275                         /* Launch notification */
3276                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3277                                                                      _CS("ckct_nw_pasting"));
3278                         if (inf_note != NULL)  {
3279                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3280                                 gtk_widget_show (GTK_WIDGET(inf_note));
3281                         }
3282                         
3283                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3284                         modest_mail_operation_xfer_folder (mail_op, 
3285                                                            src_folder,
3286                                                            folder_store,
3287                                                            delete,
3288                                                            destroy_information_note,
3289                                                            inf_note);
3290                 }
3291
3292                 /* Free */
3293                 if (data != NULL) 
3294                         g_object_unref (data);
3295                 if (src_folder != NULL) 
3296                         g_object_unref (src_folder);
3297                 if (folder_store != NULL) 
3298                         g_object_unref (folder_store);
3299         }
3300 }
3301
3302
3303 void
3304 modest_ui_actions_on_select_all (GtkAction *action,
3305                                  ModestWindow *window)
3306 {
3307         GtkWidget *focused_widget;
3308
3309         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3310         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3311                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3312         } else if (GTK_IS_LABEL (focused_widget)) {
3313                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3314         } else if (GTK_IS_EDITABLE (focused_widget)) {
3315                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3316         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3317                 GtkTextBuffer *buffer;
3318                 GtkTextIter start, end;
3319
3320                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3321                 gtk_text_buffer_get_start_iter (buffer, &start);
3322                 gtk_text_buffer_get_end_iter (buffer, &end);
3323                 gtk_text_buffer_select_range (buffer, &start, &end);
3324         } else if (GTK_IS_HTML (focused_widget)) {
3325                 gtk_html_select_all (GTK_HTML (focused_widget));
3326         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3327                 GtkWidget *header_view = focused_widget;
3328                 GtkTreeSelection *selection = NULL;
3329                 
3330                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3331                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3332                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3333                 }
3334                                 
3335                 /* Disable window dimming management */
3336                 modest_window_disable_dimming (MODEST_WINDOW(window));
3337                 
3338                 /* Select all messages */
3339                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3340                 gtk_tree_selection_select_all (selection);
3341
3342                 /* Set focuse on header view */
3343                 gtk_widget_grab_focus (header_view);
3344
3345
3346                 /* Enable window dimming management */
3347                 modest_window_enable_dimming (MODEST_WINDOW(window));
3348                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3349         }
3350
3351 }
3352
3353 void
3354 modest_ui_actions_on_mark_as_read (GtkAction *action,
3355                                    ModestWindow *window)
3356 {       
3357         g_return_if_fail (MODEST_IS_WINDOW(window));
3358                 
3359         /* Mark each header as read */
3360         do_headers_action (window, headers_action_mark_as_read, NULL);
3361 }
3362
3363 void
3364 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3365                                      ModestWindow *window)
3366 {       
3367         g_return_if_fail (MODEST_IS_WINDOW(window));
3368                 
3369         /* Mark each header as read */
3370         do_headers_action (window, headers_action_mark_as_unread, NULL);
3371 }
3372
3373 void
3374 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3375                                   GtkRadioAction *selected,
3376                                   ModestWindow *window)
3377 {
3378         gint value;
3379
3380         value = gtk_radio_action_get_current_value (selected);
3381         if (MODEST_IS_WINDOW (window)) {
3382                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3383         }
3384 }
3385
3386 void     
3387 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3388                                                GtkRadioAction *selected,
3389                                                ModestWindow *window)
3390 {
3391         TnyHeaderFlags flags;
3392         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3393
3394         flags = gtk_radio_action_get_current_value (selected);
3395         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3396 }
3397
3398 void     
3399 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3400                                                   GtkRadioAction *selected,
3401                                                   ModestWindow *window)
3402 {
3403         gint file_format;
3404
3405         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3406
3407         file_format = gtk_radio_action_get_current_value (selected);
3408         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3409 }
3410
3411
3412 void     
3413 modest_ui_actions_on_zoom_plus (GtkAction *action,
3414                                 ModestWindow *window)
3415 {
3416         g_return_if_fail (MODEST_IS_WINDOW (window));
3417
3418         modest_window_zoom_plus (MODEST_WINDOW (window));
3419 }
3420
3421 void     
3422 modest_ui_actions_on_zoom_minus (GtkAction *action,
3423                                  ModestWindow *window)
3424 {
3425         g_return_if_fail (MODEST_IS_WINDOW (window));
3426
3427         modest_window_zoom_minus (MODEST_WINDOW (window));
3428 }
3429
3430 void     
3431 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3432                                            ModestWindow *window)
3433 {
3434         ModestWindowMgr *mgr;
3435         gboolean fullscreen, active;
3436         g_return_if_fail (MODEST_IS_WINDOW (window));
3437
3438         mgr = modest_runtime_get_window_mgr ();
3439
3440         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3441         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3442
3443         if (active != fullscreen) {
3444                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3445                 gtk_window_present (GTK_WINDOW (window));
3446         }
3447 }
3448
3449 void
3450 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3451                                         ModestWindow *window)
3452 {
3453         ModestWindowMgr *mgr;
3454         gboolean fullscreen;
3455
3456         g_return_if_fail (MODEST_IS_WINDOW (window));
3457
3458         mgr = modest_runtime_get_window_mgr ();
3459         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3460         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3461
3462         gtk_window_present (GTK_WINDOW (window));
3463 }
3464
3465 /* 
3466  * Used by modest_ui_actions_on_details to call do_headers_action 
3467  */
3468 static void
3469 headers_action_show_details (TnyHeader *header, 
3470                              ModestWindow *window,
3471                              gpointer user_data)
3472
3473 {
3474         GtkWidget *dialog;
3475         
3476         /* Create dialog */
3477         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3478
3479         /* Run dialog */
3480         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3481         gtk_widget_show_all (dialog);
3482         gtk_dialog_run (GTK_DIALOG (dialog));
3483
3484         gtk_widget_destroy (dialog);
3485 }
3486
3487 /*
3488  * Show the folder details in a ModestDetailsDialog widget
3489  */
3490 static void
3491 show_folder_details (TnyFolder *folder, 
3492                      GtkWindow *window)
3493 {
3494         GtkWidget *dialog;
3495         
3496         /* Create dialog */
3497         dialog = modest_details_dialog_new_with_folder (window, folder);
3498
3499         /* Run dialog */
3500         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3501         gtk_widget_show_all (dialog);
3502         gtk_dialog_run (GTK_DIALOG (dialog));
3503
3504         gtk_widget_destroy (dialog);
3505 }
3506
3507 /*
3508  * Show the header details in a ModestDetailsDialog widget
3509  */
3510 void     
3511 modest_ui_actions_on_details (GtkAction *action, 
3512                               ModestWindow *win)
3513 {
3514         TnyList * headers_list;
3515         TnyIterator *iter;
3516         TnyHeader *header;              
3517
3518         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3519                 TnyMsg *msg;
3520
3521                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3522                 if (!msg)
3523                         return;
3524                 g_object_unref (msg);           
3525
3526                 headers_list = get_selected_headers (win);
3527                 if (!headers_list)
3528                         return;
3529
3530                 iter = tny_list_create_iterator (headers_list);
3531
3532                 header = TNY_HEADER (tny_iterator_get_current (iter));
3533                 if (header) {
3534                         headers_action_show_details (header, win, NULL);
3535                         g_object_unref (header);
3536                 }
3537
3538                 g_object_unref (iter);
3539                 g_object_unref (headers_list);
3540
3541         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3542                 GtkWidget *folder_view, *header_view;
3543
3544                 /* Check which widget has the focus */
3545                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3546                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3547                 if (gtk_widget_is_focus (folder_view)) {
3548                         TnyFolderStore *folder_store
3549                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3550                         if (!folder_store) {
3551                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3552                                 return; 
3553                         }
3554                         /* Show only when it's a folder */
3555                         /* This function should not be called for account items, 
3556                          * because we dim the menu item for them. */
3557                         if (TNY_IS_FOLDER (folder_store)) {
3558                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3559                         }
3560
3561                         g_object_unref (folder_store);
3562
3563                 } else {
3564                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3565                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3566                         /* Show details of each header */
3567                         do_headers_action (win, headers_action_show_details, header_view);
3568                 }
3569         }
3570 }
3571
3572 void     
3573 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3574                                      ModestMsgEditWindow *window)
3575 {
3576         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3577
3578         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3579 }
3580
3581 void     
3582 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3583                                       ModestMsgEditWindow *window)
3584 {
3585         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3586
3587         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3588 }
3589
3590 void
3591 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3592                                        ModestMainWindow *main_window)
3593 {
3594         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3595
3596         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3597                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3598         else
3599                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3600 }
3601
3602 void 
3603 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3604                                      ModestWindow *window)
3605 {
3606         gboolean active, fullscreen = FALSE;
3607         ModestWindowMgr *mgr;
3608
3609         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3610
3611         /* Check if we want to toggle the toolbar vuew in fullscreen
3612            or normal mode */
3613         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3614                      "ViewShowToolbarFullScreen")) {
3615                 fullscreen = TRUE;
3616         }
3617
3618         /* Toggle toolbar */
3619         mgr = modest_runtime_get_window_mgr ();
3620         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3621 }
3622
3623 void     
3624 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3625                                            ModestMsgEditWindow *window)
3626 {
3627         modest_msg_edit_window_select_font (window);
3628 }
3629
3630 void
3631 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3632                                                   const gchar *display_name,
3633                                                   GtkWindow *window)
3634 {
3635         /* Do not change the application name if the widget has not
3636            the focus. This callback could be called even if the folder
3637            view has not the focus, because the handled signal could be
3638            emitted when the folder view is redrawn */
3639         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3640                 if (display_name)
3641                         gtk_window_set_title (window, display_name);
3642                 else
3643                         gtk_window_set_title (window, " ");
3644         }
3645 }
3646
3647 void
3648 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3649 {
3650         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3651         modest_msg_edit_window_select_contacts (window);
3652 }
3653
3654 void
3655 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3656 {
3657         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3658         modest_msg_edit_window_check_names (window, FALSE);
3659 }
3660
3661 static void
3662 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3663 {
3664         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3665                                          GTK_WIDGET (user_data));
3666 }
3667
3668 /*
3669  * This function is used to track changes in the selection of the
3670  * folder view that is inside the "move to" dialog to enable/disable
3671  * the OK button because we do not want the user to select a disallowed
3672  * destination for a folder.
3673  * The user also not desired to be able to use NEW button on items where
3674  * folder creation is not possibel.
3675  */
3676 static void
3677 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3678                                             TnyFolderStore *folder_store,
3679                                             gboolean selected,
3680                                             gpointer user_data)
3681 {
3682         GtkWidget *dialog = NULL;
3683         GtkWidget *ok_button = NULL, *new_button = NULL;
3684         GList *children = NULL;
3685         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3686         gboolean moving_folder = FALSE;
3687         gboolean is_local_account = TRUE;
3688         GtkWidget *folder_view = NULL;
3689         ModestTnyFolderRules rules;
3690
3691         if (!selected)
3692                 return;
3693
3694         /* Get the OK button */
3695         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3696         if (!dialog)
3697                 return;
3698
3699         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3700         ok_button = GTK_WIDGET (children->next->next->data);
3701         new_button = GTK_WIDGET (children->next->data);
3702         g_list_free (children);
3703
3704         /* check if folder_store is an remote account */
3705         if (TNY_IS_ACCOUNT (folder_store)) {
3706                 TnyAccount *local_account = NULL;
3707                 TnyAccount *mmc_account = NULL;
3708                 ModestTnyAccountStore *account_store = NULL;
3709
3710                 account_store = modest_runtime_get_account_store ();
3711                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3712                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3713
3714                 if ((gpointer) local_account != (gpointer) folder_store &&
3715                     (gpointer) mmc_account != (gpointer) folder_store) {
3716                         is_local_account = FALSE;
3717                         /* New button should be dimmed on remote
3718                            account root */
3719                         new_sensitive = FALSE;
3720                 }
3721                 g_object_unref (local_account);
3722         }
3723
3724         /* Check the target folder rules */
3725         if (TNY_IS_FOLDER (folder_store)) {
3726                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3727                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3728                         ok_sensitive = FALSE;
3729                         new_sensitive = FALSE;
3730                         goto end;
3731                 }
3732         }
3733
3734         /* Check if we're moving a folder */
3735         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3736                 /* Get the widgets */
3737                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3738                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3739                 if (gtk_widget_is_focus (folder_view))
3740                         moving_folder = TRUE;
3741         }
3742
3743         if (moving_folder) {
3744                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3745
3746                 /* Get the folder to move */
3747                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3748                 
3749                 /* Check that we're not moving to the same folder */
3750                 if (TNY_IS_FOLDER (moved_folder)) {
3751                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3752                         if (parent == folder_store)
3753                                 ok_sensitive = FALSE;
3754                         g_object_unref (parent);
3755                 } 
3756
3757                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3758                         /* Do not allow to move to an account unless it's the
3759                            local folders account */
3760                         if (!is_local_account)
3761                                 ok_sensitive = FALSE;
3762                 } 
3763
3764                 if (ok_sensitive && (moved_folder == folder_store)) {
3765                         /* Do not allow to move to itself */
3766                         ok_sensitive = FALSE;
3767                 }
3768                 g_object_unref (moved_folder);
3769         } else {
3770                 TnyHeader *header = NULL;
3771                 TnyFolder *src_folder = NULL;
3772
3773                 /* Moving a message */
3774                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3775                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3776                         src_folder = tny_header_get_folder (header);
3777                         g_object_unref (header);
3778                 } else {
3779                         src_folder = 
3780                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3781                 }
3782
3783                 /* Do not allow to move the msg to the same folder */
3784                 /* Do not allow to move the msg to an account */
3785                 if ((gpointer) src_folder == (gpointer) folder_store ||
3786                     TNY_IS_ACCOUNT (folder_store))
3787                         ok_sensitive = FALSE;
3788                 g_object_unref (src_folder);
3789         }
3790
3791  end:
3792         /* Set sensitivity of the OK button */
3793         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3794         /* Set sensitivity of the NEW button */
3795         gtk_widget_set_sensitive (new_button, new_sensitive);
3796 }
3797
3798 static GtkWidget*
3799 create_move_to_dialog (GtkWindow *win,
3800                        GtkWidget *folder_view,
3801                        GtkWidget **tree_view)
3802 {
3803         GtkWidget *dialog, *scroll;
3804         GtkWidget *new_button;
3805
3806         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3807                                               GTK_WINDOW (win),
3808                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3809                                               NULL);
3810
3811         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3812         /* We do this manually so GTK+ does not associate a response ID for
3813          * the button. */
3814         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3815         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3816         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3817
3818         /* Create scrolled window */
3819         scroll = gtk_scrolled_window_new (NULL, NULL);
3820         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3821                                          GTK_POLICY_AUTOMATIC,
3822                                          GTK_POLICY_AUTOMATIC);
3823
3824         /* Create folder view */
3825         *tree_view = modest_platform_create_folder_view (NULL);
3826
3827         /* Track changes in the selection to
3828          * disable the OK button whenever "Move to" is not possible
3829          * disbale NEW button whenever New is not possible */
3830         g_signal_connect (*tree_view,
3831                           "folder_selection_changed",
3832                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3833                           win);
3834
3835         /* Listen to clicks on New button */
3836         g_signal_connect (G_OBJECT (new_button), 
3837                           "clicked", 
3838                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3839                           *tree_view);
3840
3841         /* It could happen that we're trying to move a message from a
3842            window (msg window for example) after the main window was
3843            closed, so we can not just get the model of the folder
3844            view */
3845         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3846                 const gchar *visible_id = NULL;
3847
3848                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3849                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3850                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3851                                                MODEST_FOLDER_VIEW(*tree_view));
3852
3853                 visible_id = 
3854                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3855
3856                 /* Show the same account than the one that is shown in the main window */
3857                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3858                                                                              visible_id);
3859         } else {
3860                 const gchar *active_account_name = NULL;
3861                 ModestAccountMgr *mgr = NULL;
3862                 ModestAccountData *acc_data = NULL;
3863
3864                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3865                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3866                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3867                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3868
3869                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3870                 mgr = modest_runtime_get_account_mgr ();
3871                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3872
3873                 /* Set the new visible & active account */
3874                 if (acc_data && acc_data->store_account) { 
3875                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3876                                                                                      acc_data->store_account->account_name);
3877                         modest_account_mgr_free_account_data (mgr, acc_data);
3878                 }
3879         }
3880
3881         /* Hide special folders */
3882         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3883         
3884         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3885
3886         /* Add scroll to dialog */
3887         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3888                             scroll, TRUE, TRUE, 0);
3889
3890         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3891         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3892
3893         return dialog;
3894 }
3895
3896 /*
3897  * Returns TRUE if at least one of the headers of the list belongs to
3898  * a message that has been fully retrieved.
3899  */
3900 #if 0 /* no longer in use. delete in 2007.10 */
3901 static gboolean
3902 has_retrieved_msgs (TnyList *list)
3903 {
3904         TnyIterator *iter;
3905         gboolean found = FALSE;
3906
3907         iter = tny_list_create_iterator (list);
3908         while (!tny_iterator_is_done (iter) && !found) {
3909                 TnyHeader *header;
3910                 TnyHeaderFlags flags = 0;
3911
3912                 header = TNY_HEADER (tny_iterator_get_current (iter));
3913                 if (header) {
3914                         flags = tny_header_get_flags (header);
3915                         if (flags & TNY_HEADER_FLAG_CACHED)
3916 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3917                                 found = TRUE;
3918
3919                         g_object_unref (header);
3920                 }
3921
3922                 if (!found)
3923                         tny_iterator_next (iter);
3924         }
3925         g_object_unref (iter);
3926
3927         return found;
3928 }
3929 #endif /* 0 */
3930
3931
3932 /*
3933  * Shows a confirmation dialog to the user when we're moving messages
3934  * from a remote server to the local storage. Returns the dialog
3935  * response. If it's other kind of movement then it always returns
3936  * GTK_RESPONSE_OK
3937  *
3938  * This one is used by the next functions:
3939  *      modest_ui_actions_on_paste                      - commented out
3940  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3941  */
3942 gint
3943 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
3944                                              TnyFolder *dest_folder,
3945                                              gboolean delete,
3946                                              TnyList *headers)
3947 {
3948         gint response = GTK_RESPONSE_OK;
3949         TnyAccount *account = NULL;
3950         TnyFolder *src_folder = NULL;
3951         TnyIterator *iter = NULL;
3952         TnyHeader *header = NULL;
3953
3954         /* return with OK if the destination is a remote folder */
3955         if (modest_tny_folder_is_remote_folder (dest_folder))
3956                 return GTK_RESPONSE_OK;
3957
3958         /* Get source folder */
3959         iter = tny_list_create_iterator (headers);
3960         header = TNY_HEADER (tny_iterator_get_current (iter));
3961         if (header) {
3962                 src_folder = tny_header_get_folder (header);
3963                 g_object_unref (header);
3964         }
3965         g_object_unref (iter);
3966
3967         /* if no src_folder, message may be an attahcment */
3968         if (src_folder == NULL) 
3969                 return GTK_RESPONSE_CANCEL;
3970
3971         /* If the source is a local or MMC folder */
3972         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3973                 g_object_unref (src_folder);
3974                 return GTK_RESPONSE_OK;
3975         }
3976
3977         /* Get the account */
3978         account = tny_folder_get_account (src_folder);
3979
3980         /* now if offline we ask the user */
3981         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
3982                 response = GTK_RESPONSE_OK;
3983         else
3984                 response = GTK_RESPONSE_CANCEL;
3985
3986         /* Frees */
3987         g_object_unref (src_folder);
3988         g_object_unref (account);
3989
3990         return response;
3991 }
3992
3993
3994
3995 static void
3996 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
3997 {
3998         MoveToHelper *helper = (MoveToHelper *) user_data;
3999
4000         /* Note that the operation could have failed, in that case do
4001            nothing */
4002         if (modest_mail_operation_get_status (mail_op) == 
4003             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4004
4005                 GObject *object = modest_mail_operation_get_source (mail_op);
4006                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4007                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4008
4009                         if (!modest_msg_view_window_select_next_message (self))
4010                                 if (!modest_msg_view_window_select_previous_message (self))
4011                                         /* No more messages to view, so close this window */
4012                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4013                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4014                         GtkWidget *header_view;
4015                         GtkTreePath *path;
4016                         GtkTreeSelection *sel;
4017
4018                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4019                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4020                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4021                         path = gtk_tree_row_reference_get_path (helper->reference);
4022                         gtk_tree_selection_select_path (sel, path);
4023                         gtk_tree_path_free (path);
4024                 }
4025                 g_object_unref (object);
4026         }
4027
4028         /* Close the "Pasting" information banner */
4029         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4030         if (helper->reference != NULL)
4031                 gtk_tree_row_reference_free (helper->reference);
4032         g_free (helper);
4033 }
4034
4035 void
4036 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4037                                              gpointer user_data)
4038 {
4039         ModestWindow *main_window = NULL;
4040         GObject *win = NULL;
4041         const GError *error = NULL;
4042         const gchar *message = NULL;
4043         
4044         /* Get error message */
4045         error = modest_mail_operation_get_error (mail_op);
4046         if (error != NULL && error->message != NULL) {
4047                 message = error->message;
4048         } else {
4049                 message = _("mail_in_ui_folder_move_target_error");
4050         }
4051         
4052         /* Disable next automatic folder selection */
4053         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4054                                                          FALSE); /* don't create */
4055         if (main_window) {
4056                 GtkWidget *folder_view = NULL;
4057         
4058                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4059                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4060                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4061                 
4062                 if (user_data && TNY_IS_FOLDER (user_data)) {
4063                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4064                                                           TNY_FOLDER (user_data), FALSE);
4065                 }
4066         }
4067
4068         /* Show notification dialog */
4069         win = modest_mail_operation_get_source (mail_op);
4070         if (G_IS_OBJECT (win)) {
4071                 modest_platform_run_information_dialog (GTK_WINDOW (win), message);
4072                 g_object_unref (win);
4073         }
4074 }
4075
4076 void
4077 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4078                                               gpointer user_data)
4079 {
4080         GObject *win = modest_mail_operation_get_source (mail_op);
4081         const GError *error = modest_mail_operation_get_error (mail_op);
4082
4083         g_return_if_fail (error != NULL);
4084         if (error->message != NULL)             
4085                 g_printerr ("modest: %s\n", error->message);
4086         else
4087                 g_printerr ("modest: unkonw error on send&receive operation");
4088
4089         /* Show error message */
4090 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4091 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4092 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4093 /*      else  */
4094 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4095 /*                                                      _CS("sfil_ib_unable_to_send")); */
4096         g_object_unref (win);
4097 }
4098
4099 static void
4100 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4101                        TnyHeader *header, 
4102                        TnyMsg *msg, 
4103                        gpointer user_data)
4104 {
4105         TnyList *parts;
4106         TnyIterator *iter;
4107         gint pending_purges = 0;
4108         gboolean some_purged = FALSE;
4109         ModestWindow *win = MODEST_WINDOW (user_data);
4110         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4111
4112         /* If there was any error */
4113         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4114                 modest_window_mgr_unregister_header (mgr, header);
4115                 return;
4116         }
4117
4118         /* Once the message has been retrieved for purging, we check if
4119          * it's all ok for purging */
4120
4121         parts = tny_simple_list_new ();
4122         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4123         iter = tny_list_create_iterator (parts);
4124
4125         while (!tny_iterator_is_done (iter)) {
4126                 TnyMimePart *part;
4127                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4128                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4129                         if (tny_mime_part_is_purged (part))
4130                                 some_purged = TRUE;
4131                         else
4132                                 pending_purges++;
4133                 }
4134
4135                 if (part)
4136                         g_object_unref (part);
4137
4138                 tny_iterator_next (iter);
4139         }
4140         g_object_unref (iter);
4141         
4142
4143         if (pending_purges>0) {
4144                 gint response;
4145                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4146
4147                 if (response == GTK_RESPONSE_OK) {
4148                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4149                         iter = tny_list_create_iterator (parts);
4150                         while (!tny_iterator_is_done (iter)) {
4151                                 TnyMimePart *part;
4152                                 
4153                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4154                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4155                                         tny_mime_part_set_purged (part);
4156
4157                                 if (part)
4158                                         g_object_unref (part);
4159
4160                                 tny_iterator_next (iter);
4161                         }
4162                         
4163                         tny_msg_rewrite_cache (msg);
4164                 }
4165         } else {
4166                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4167         }
4168         g_object_unref (iter);
4169
4170         modest_window_mgr_unregister_header (mgr, header);
4171
4172         g_object_unref (parts);
4173 }
4174
4175 static void
4176 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4177                                                      ModestMainWindow *win)
4178 {
4179         GtkWidget *header_view;
4180         TnyList *header_list;
4181         TnyIterator *iter;
4182         TnyHeader *header;
4183         TnyHeaderFlags flags;
4184         ModestWindow *msg_view_window =  NULL;
4185         gboolean found;
4186
4187         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4188
4189         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4190                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4191
4192         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4193         if (!header_list) {
4194                 g_warning ("%s: no header selected", __FUNCTION__);
4195                 return;
4196         }
4197         
4198         if (tny_list_get_length (header_list) == 1) {
4199                 iter = tny_list_create_iterator (header_list);
4200                 header = TNY_HEADER (tny_iterator_get_current (iter));
4201                 g_object_unref (iter);
4202         } else
4203                 return;
4204         
4205         if (!header || !TNY_IS_HEADER(header)) {
4206                 g_warning ("%s: header is not valid", __FUNCTION__);
4207                 return;
4208         }
4209         
4210         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4211                                                           header, &msg_view_window);
4212         flags = tny_header_get_flags (header);
4213         if (!(flags & TNY_HEADER_FLAG_CACHED))
4214                 return;
4215         if (found) {
4216                 if (msg_view_window != NULL) 
4217                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4218                 else {
4219                         /* do nothing; uid was registered before, so window is probably on it's way */
4220                         g_warning ("debug: header %p has already been registered", header);
4221                 }
4222         } else {
4223                 ModestMailOperation *mail_op = NULL;
4224                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4225                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4226                                                                          modest_ui_actions_get_msgs_full_error_handler,
4227                                                                          NULL, NULL);
4228                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4229                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4230                 
4231                 g_object_unref (mail_op);
4232         }
4233         if (header)
4234                 g_object_unref (header);
4235         if (header_list)
4236                 g_object_unref (header_list);
4237 }
4238
4239 /**
4240  * Utility function that transfer messages from both the main window
4241  * and the msg view window when using the "Move to" dialog
4242  */
4243 static void
4244 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4245                                               ModestWindow *win)
4246 {
4247         TnyList *headers = NULL;
4248         TnyAccount *dst_account = NULL;
4249         const gchar *proto_str = NULL;
4250         gboolean dst_is_pop = FALSE;
4251
4252         if (!TNY_IS_FOLDER (dst_folder)) {
4253                 modest_platform_information_banner (GTK_WIDGET (win),
4254                                                     NULL,
4255                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4256                 return;
4257         }
4258
4259         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4260         proto_str = tny_account_get_proto (dst_account);
4261
4262         /* tinymail will return NULL for local folders it seems */
4263         dst_is_pop = proto_str &&
4264                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4265                  MODEST_PROTOCOL_STORE_POP);
4266
4267         g_object_unref (dst_account);
4268
4269         /* Get selected headers */
4270         headers = get_selected_headers (MODEST_WINDOW (win));
4271         if (!headers) {
4272                 g_warning ("%s: no headers selected", __FUNCTION__);
4273                 return;
4274         }
4275
4276
4277         if (dst_is_pop) {
4278                 modest_platform_information_banner (GTK_WIDGET (win),
4279                                                     NULL,
4280                                                     ngettext("mail_in_ui_folder_move_target_error",
4281                                                              "mail_in_ui_folder_move_targets_error",
4282                                                              tny_list_get_length (headers)));
4283                 g_object_unref (headers);
4284                 return;
4285         }
4286
4287         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4288         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4289                                                            _CS("ckct_nw_pasting"));
4290         if (helper->banner != NULL)  {
4291                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4292                 gtk_widget_show (GTK_WIDGET(helper->banner));
4293         }
4294
4295         if (MODEST_IS_MAIN_WINDOW (win)) {
4296                 GtkWidget *header_view = 
4297                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4298                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4299                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4300         }
4301
4302         ModestMailOperation *mail_op = 
4303                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4304                                                                modest_ui_actions_move_folder_error_handler,
4305                                                                NULL, NULL);
4306         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4307                                          mail_op);
4308
4309         modest_mail_operation_xfer_msgs (mail_op, 
4310                                          headers,
4311                                          TNY_FOLDER (dst_folder),
4312                                          TRUE,
4313                                          move_to_cb,
4314                                          helper);
4315
4316         g_object_unref (G_OBJECT (mail_op));
4317         g_object_unref (headers);
4318 }
4319
4320 /*
4321  * UI handler for the "Move to" action when invoked from the
4322  * ModestMainWindow
4323  */
4324 static void 
4325 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4326                                           GtkWidget *folder_view,
4327                                           TnyFolderStore *dst_folder,
4328                                           ModestMainWindow *win)
4329 {
4330         ModestHeaderView *header_view = NULL;
4331         ModestMailOperation *mail_op = NULL;
4332         TnyFolderStore *src_folder;
4333         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4334
4335         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4336
4337         /* Get the source folder */
4338         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4339
4340         /* Get header view */
4341         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4342
4343         /* Get folder or messages to transfer */
4344         if (gtk_widget_is_focus (folder_view)) {
4345                 GtkTreeSelection *sel;
4346                 gboolean do_xfer = TRUE;
4347
4348                 /* Allow only to transfer folders to the local root folder */
4349                 if (TNY_IS_ACCOUNT (dst_folder) && 
4350                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4351                         do_xfer = FALSE;
4352                 } else if (!TNY_IS_FOLDER (src_folder)) {
4353                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4354                         do_xfer = FALSE;
4355                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4356                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4357                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4358                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4359                                 do_xfer = FALSE;
4360                         g_object_unref (account);
4361                 }
4362
4363                 if (do_xfer) {
4364                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4365                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4366                                                                            _CS("ckct_nw_pasting"));
4367                         if (helper->banner != NULL)  {
4368                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4369                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4370                         }
4371                         /* Clean folder on header view before moving it */
4372                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4373                         gtk_tree_selection_unselect_all (sel);
4374
4375                         /* Let gtk events run. We need that the folder
4376                            view frees its reference to the source
4377                            folder *before* issuing the mail operation
4378                            so we need the signal handler of selection
4379                            changed to happen before the mail
4380                            operation */
4381                         while (gtk_events_pending ())
4382                                 gtk_main_iteration ();
4383
4384                         mail_op =
4385                           modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4386                                                                          modest_ui_actions_move_folder_error_handler,
4387                                                                          src_folder, NULL);
4388                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4389                                                          mail_op);
4390
4391                         /* Select *after* the changes */
4392                         /* TODO: this function hangs UI after transfer */ 
4393 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4394 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4395                         
4396                         modest_mail_operation_xfer_folder (mail_op,
4397                                                            TNY_FOLDER (src_folder),
4398                                                            dst_folder,
4399                                                            TRUE, 
4400                                                            move_to_cb, 
4401                                                            helper);
4402                         /* Unref mail operation */
4403                         g_object_unref (G_OBJECT (mail_op));
4404                 }
4405         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4406                 gboolean do_xfer = TRUE;
4407                 /* Ask for confirmation if the source folder is remote and we're not connected */
4408                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4409                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4410                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4411                                 guint num_headers = tny_list_get_length(headers);
4412                                 TnyAccount *account = get_account_from_header_list (headers);
4413                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4414                                         do_xfer = FALSE;
4415                                 g_object_unref (account);
4416                         }
4417                         g_object_unref(headers);
4418                 }
4419                 if (do_xfer) /* Transfer messages */
4420                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4421         }
4422
4423     if (src_folder)
4424         g_object_unref (src_folder);
4425 }
4426
4427
4428 /*
4429  * UI handler for the "Move to" action when invoked from the
4430  * ModestMsgViewWindow
4431  */
4432 static void 
4433 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4434                                               TnyFolderStore *dst_folder,
4435                                               ModestMsgViewWindow *win)
4436 {
4437         TnyHeader *header = NULL;
4438         TnyFolder *src_folder = NULL;
4439         TnyAccount *account = NULL;
4440         gboolean do_xfer = FALSE;
4441
4442         /* Create header list */
4443         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4444         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4445         g_object_unref (header);
4446
4447         account = tny_folder_get_account (src_folder);
4448         if (!modest_platform_is_network_folderstore(TNY_FOLDER_STORE(src_folder))) {
4449                 /* Transfer if the source folder is local */
4450                 do_xfer = TRUE;
4451         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4452                 /* Transfer if the source folder is POP (as it means
4453                  * that the message is already downloaded) */
4454                 do_xfer = TRUE;
4455         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4456                 /* Transfer after asking confirmation */
4457                 do_xfer = TRUE;
4458         }
4459
4460         if (do_xfer) {
4461                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4462         }
4463         g_object_unref (account);
4464         g_object_unref (src_folder);
4465 }
4466
4467 void 
4468 modest_ui_actions_on_move_to (GtkAction *action, 
4469                               ModestWindow *win)
4470 {
4471         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4472         gint result = 0;
4473         TnyFolderStore *dst_folder = NULL;
4474         ModestMainWindow *main_window;
4475
4476         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4477                           MODEST_IS_MSG_VIEW_WINDOW (win));
4478
4479         /* Get the main window if exists */
4480         if (MODEST_IS_MAIN_WINDOW (win))
4481                 main_window = MODEST_MAIN_WINDOW (win);
4482         else
4483                 main_window = 
4484                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4485                                                                                FALSE)); /* don't create */
4486
4487         /* Get the folder view widget if exists */
4488         if (main_window)
4489                 folder_view = modest_main_window_get_child_widget (main_window,
4490                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4491         else
4492                 folder_view = NULL;
4493
4494         /* Create and run the dialog */
4495         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4496         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4497         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4498         result = gtk_dialog_run (GTK_DIALOG(dialog));
4499         g_object_ref (tree_view);
4500         gtk_widget_destroy (dialog);
4501
4502         if (result != GTK_RESPONSE_ACCEPT)
4503                 return;
4504
4505         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4506         /* Do window specific stuff */
4507         if (MODEST_IS_MAIN_WINDOW (win)) {
4508                 modest_ui_actions_on_main_window_move_to (action,
4509                                                           folder_view,
4510                                                           dst_folder,
4511                                                           MODEST_MAIN_WINDOW (win));
4512         } else {
4513                 modest_ui_actions_on_msg_view_window_move_to (action,
4514                                                               dst_folder,
4515                                                               MODEST_MSG_VIEW_WINDOW (win));
4516         }
4517
4518         if (dst_folder)
4519                 g_object_unref (dst_folder);
4520 }
4521
4522 /*
4523  * Calls #HeadersFunc for each header already selected in the main
4524  * window or the message currently being shown in the msg view window
4525  */
4526 static void
4527 do_headers_action (ModestWindow *win, 
4528                    HeadersFunc func,
4529                    gpointer user_data)
4530 {
4531         TnyList *headers_list = NULL;
4532         TnyIterator *iter = NULL;
4533         TnyHeader *header = NULL;
4534         TnyFolder *folder = NULL;
4535
4536         /* Get headers */
4537         headers_list = get_selected_headers (win);
4538         if (!headers_list)
4539                 return;
4540
4541         /* Get the folder */
4542         iter = tny_list_create_iterator (headers_list);
4543         header = TNY_HEADER (tny_iterator_get_current (iter));
4544         if (header) {
4545                 folder = tny_header_get_folder (header);
4546                 g_object_unref (header);
4547         }
4548
4549         /* Call the function for each header */
4550         while (!tny_iterator_is_done (iter)) {
4551                 header = TNY_HEADER (tny_iterator_get_current (iter));
4552                 func (header, win, user_data);
4553                 g_object_unref (header);
4554                 tny_iterator_next (iter);
4555         }
4556
4557         /* Trick: do a poke status in order to speed up the signaling
4558            of observers */
4559         tny_folder_poke_status (folder);
4560
4561         /* Frees */
4562         g_object_unref (folder);
4563         g_object_unref (iter);
4564         g_object_unref (headers_list);
4565 }
4566
4567 void 
4568 modest_ui_actions_view_attachment (GtkAction *action,
4569                                    ModestWindow *window)
4570 {
4571         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4572                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4573         } else {
4574                 /* not supported window for this action */
4575                 g_return_if_reached ();
4576         }
4577 }
4578
4579 void
4580 modest_ui_actions_save_attachments (GtkAction *action,
4581                                     ModestWindow *window)
4582 {
4583         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4584                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4585         } else {
4586                 /* not supported window for this action */
4587                 g_return_if_reached ();
4588         }
4589 }
4590
4591 void
4592 modest_ui_actions_remove_attachments (GtkAction *action,
4593                                       ModestWindow *window)
4594 {
4595         if (MODEST_IS_MAIN_WINDOW (window)) {
4596                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4597         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4598                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4599         } else {
4600                 /* not supported window for this action */
4601                 g_return_if_reached ();
4602         }
4603 }
4604
4605 void 
4606 modest_ui_actions_on_settings (GtkAction *action, 
4607                                ModestWindow *win)
4608 {
4609         GtkWidget *dialog;
4610
4611         dialog = modest_platform_get_global_settings_dialog ();
4612         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4613         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4614         gtk_widget_show_all (dialog);
4615
4616         gtk_dialog_run (GTK_DIALOG (dialog));
4617
4618         gtk_widget_destroy (dialog);
4619 }
4620
4621 void 
4622 modest_ui_actions_on_help (GtkAction *action, 
4623                            GtkWindow *win)
4624 {
4625         const gchar *help_id;
4626
4627         g_return_if_fail (action);
4628         g_return_if_fail (win && GTK_IS_WINDOW(win));
4629         
4630         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4631         
4632         if (help_id)
4633                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4634         else
4635                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4636 }
4637
4638 void 
4639 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4640                                             ModestWindow *window)
4641 {
4642         ModestMailOperation *mail_op;
4643         TnyList *headers;
4644
4645         /* Get headers */
4646         headers = get_selected_headers (window);
4647         if (!headers)
4648                 return;
4649
4650         /* Create mail operation */
4651         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (window),
4652                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4653                                                                  NULL, NULL);
4654         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4655         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4656
4657         /* Frees */
4658         g_object_unref (headers);
4659         g_object_unref (mail_op);
4660 }
4661
4662 void
4663 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4664                                           ModestWindow *window)
4665 {
4666         g_return_if_fail (MODEST_IS_WINDOW (window));
4667         
4668         /* Update dimmed */     
4669         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4670 }
4671
4672 void
4673 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4674                                           ModestWindow *window)
4675 {
4676         g_return_if_fail (MODEST_IS_WINDOW (window));
4677
4678         /* Update dimmed */     
4679         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4680 }
4681
4682 void
4683 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4684                                           ModestWindow *window)
4685 {
4686         g_return_if_fail (MODEST_IS_WINDOW (window));
4687
4688         /* Update dimmed */     
4689         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4690 }
4691
4692 void
4693 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4694                                             ModestWindow *window)
4695 {
4696         g_return_if_fail (MODEST_IS_WINDOW (window));
4697
4698         /* Update dimmed */     
4699         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4700 }
4701
4702 void
4703 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4704                                           ModestWindow *window)
4705 {
4706         g_return_if_fail (MODEST_IS_WINDOW (window));
4707
4708         /* Update dimmed */     
4709         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4710 }
4711
4712 void
4713 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4714                                           ModestWindow *window)
4715 {
4716         g_return_if_fail (MODEST_IS_WINDOW (window));
4717
4718         /* Update dimmed */     
4719         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4720 }
4721
4722 void
4723 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4724                                                  ModestWindow *window)
4725 {
4726         g_return_if_fail (MODEST_IS_WINDOW (window));
4727
4728         /* Update dimmed */     
4729         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4730 }
4731
4732 void
4733 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4734                                                      ModestWindow *window)
4735 {
4736         g_return_if_fail (MODEST_IS_WINDOW (window));
4737
4738         /* Update dimmed */     
4739         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4740 }
4741
4742 void
4743 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4744                                                      ModestWindow *window)
4745 {
4746         g_return_if_fail (MODEST_IS_WINDOW (window));
4747
4748         /* Update dimmed */     
4749         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4750 }
4751
4752 void
4753 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4754 {
4755         g_return_if_fail (MODEST_IS_WINDOW (window));
4756
4757         /* Update dimmed */     
4758         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4759 }
4760
4761 void
4762 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4763 {
4764         g_return_if_fail (MODEST_IS_WINDOW (window));
4765
4766         modest_platform_show_search_messages (GTK_WINDOW (window));
4767 }
4768
4769 void     
4770 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4771 {
4772         g_return_if_fail (MODEST_IS_WINDOW (win));
4773         modest_platform_show_addressbook (GTK_WINDOW (win));
4774 }
4775
4776
4777 void
4778 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4779                                           ModestWindow *window)
4780 {
4781         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4782
4783         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4784 }
4785
4786 static void 
4787 on_send_receive_finished (ModestMailOperation  *mail_op, 
4788                            gpointer user_data)
4789 {
4790         /* Set send/receive operation finished */       
4791         modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW (user_data));      
4792 }
4793
4794
4795 void 
4796 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4797                                                 TnyHeader *header, 
4798                                                 TnyMsg *msg, 
4799                                                 GError *err, 
4800                                                 gpointer user_data)
4801 {
4802         const gchar* server_name = NULL;
4803         TnyTransportAccount *server_account;
4804         gchar *message = NULL;
4805
4806         /* Don't show anything if the user cancelled something */
4807         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4808                 return;
4809
4810         /* Get the server name: */
4811         server_account = 
4812                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4813         if (server_account) {
4814                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4815                         
4816                 g_object_unref (server_account);
4817                 server_account = NULL;
4818         }
4819         
4820         g_return_if_fail (server_name);
4821
4822         /* Show the appropriate message text for the GError: */
4823         switch (err->code) {
4824         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4825                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4826                 break;
4827         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4828                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4829                 break;
4830         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4831                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4832                 break;
4833         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4834                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4835                 break;
4836         default:
4837                 g_return_if_reached ();
4838         }
4839         
4840         /* TODO if the username or the password where not defined we
4841            should show the Accounts Settings dialog or the Connection
4842            specific SMTP server window */
4843
4844         modest_platform_run_information_dialog (NULL, message);
4845         g_free (message);
4846 }
4847
4848 void
4849 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4850                                                 gchar *msg_id, 
4851                                                 guint status,
4852                                                 gpointer user_data)
4853 {
4854         ModestMainWindow *main_window = NULL;
4855         ModestWindowMgr *mgr = NULL;
4856         GtkWidget *folder_view = NULL, *header_view = NULL;
4857         TnyFolderStore *selected_folder = NULL;
4858         TnyFolderType folder_type;
4859
4860         mgr = modest_runtime_get_window_mgr ();
4861         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
4862                                                                              FALSE));/* don't create */
4863         if (!main_window)
4864                 return;
4865
4866         /* Check if selected folder is OUTBOX */
4867         folder_view = modest_main_window_get_child_widget (main_window,
4868                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4869         header_view = modest_main_window_get_child_widget (main_window,
4870                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4871
4872         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4873         if (!TNY_IS_FOLDER (selected_folder)) 
4874                 goto frees;
4875
4876         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4877 #if GTK_CHECK_VERSION(2, 8, 0) 
4878         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4879         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4880                 GtkTreeViewColumn *tree_column;
4881
4882                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4883                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4884                 gtk_tree_view_column_queue_resize (tree_column);
4885         }
4886 #else
4887         gtk_widget_queue_draw (header_view);
4888 #endif          
4889         
4890         /* Free */
4891  frees:
4892         if (selected_folder != NULL)
4893                 g_object_unref (selected_folder);
4894 }