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