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