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