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