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