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