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