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