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