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