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