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