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