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