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