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