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