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