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