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