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