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