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