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