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