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