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