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