18468d8dce694605aaf7ab566bfb58f2802db564
[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         ModestConf *conf;
2647         GtkWidget *header_view;
2648
2649         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2650
2651         header_view = modest_main_window_get_child_widget(main_window,
2652                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2653         if (!header_view)
2654                 return;
2655
2656         conf = modest_runtime_get_conf ();
2657
2658         if (TNY_IS_ACCOUNT (folder_store)) {
2659                 if (selected) {
2660                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2661
2662                         /* Show account details */
2663                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2664                 }
2665         } else {
2666                 if (TNY_IS_FOLDER (folder_store) && selected) {
2667                         TnyAccount *account;
2668                         const gchar *account_name = NULL;
2669
2670                         /* Update the active account */
2671                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2672                         if (account) {
2673                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2674                                 account_name =
2675                                         modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2676                                 g_object_unref (account);
2677                                 account = NULL;
2678                         }
2679
2680                         /* Set the header style by default, it could
2681                            be changed later by the refresh callback to
2682                            empty */
2683                         modest_main_window_set_contents_style (main_window,
2684                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2685
2686                         /* Set folder on header view. This function
2687                            will call tny_folder_refresh_async so we
2688                            pass a callback that will be called when
2689                            finished. We use that callback to set the
2690                            empty view if there are no messages */
2691                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2692                                                        TNY_FOLDER (folder_store),
2693                                                        TRUE,
2694                                                        MODEST_WINDOW (main_window),
2695                                                        folder_refreshed_cb,
2696                                                        main_window);
2697
2698                         /* Restore configuration. We need to do this
2699                            *after* the set_folder because the widget
2700                            memory asks the header view about its
2701                            folder  */
2702                         modest_widget_memory_restore (modest_runtime_get_conf (),
2703                                                       G_OBJECT(header_view),
2704                                                       MODEST_CONF_HEADER_VIEW_KEY);
2705                 } else {
2706                         /* No need to save the header view
2707                            configuration for Maemo because it only
2708                            saves the sorting stuff and that it's
2709                            already being done by the sort
2710                            dialog. Remove it when the GNOME version
2711                            has the same behaviour */
2712 #ifdef MODEST_TOOLKIT_GTK
2713                         if (modest_main_window_get_contents_style (main_window) ==
2714                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2715                                 modest_widget_memory_save (conf, G_OBJECT (header_view),
2716                                                            MODEST_CONF_HEADER_VIEW_KEY);
2717 #endif
2718                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2719                 }
2720         }
2721
2722         /* Update dimming state */
2723         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2724         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2725 }
2726
2727 void
2728 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2729                                      ModestWindow *win)
2730 {
2731         GtkWidget *dialog;
2732         gchar *txt, *item;
2733         gboolean online;
2734
2735         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2736
2737         online = tny_device_is_online (modest_runtime_get_device());
2738
2739         if (online) {
2740                 /* already online -- the item is simply not there... */
2741                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2742                                                  GTK_DIALOG_MODAL,
2743                                                  GTK_MESSAGE_WARNING,
2744                                                  GTK_BUTTONS_NONE,
2745                                                  _("The %s you selected cannot be found"),
2746                                                  item);
2747                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2748                 gtk_dialog_run (GTK_DIALOG(dialog));
2749         } else {
2750                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2751                                                       GTK_WINDOW (win),
2752                                                       GTK_DIALOG_MODAL,
2753                                                       _("mcen_bd_dialog_cancel"),
2754                                                       GTK_RESPONSE_REJECT,
2755                                                       _("mcen_bd_dialog_ok"),
2756                                                       GTK_RESPONSE_ACCEPT,
2757                                                       NULL);
2758                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2759                                          "Do you want to get online?"), item);
2760                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2761                                     gtk_label_new (txt), FALSE, FALSE, 0);
2762                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2763                 g_free (txt);
2764
2765                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2766                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2767                         /* TODO: Comment about why is this commented out: */
2768                         /* modest_platform_connect_and_wait (); */
2769                 }
2770         }
2771         gtk_widget_destroy (dialog);
2772 }
2773
2774 void
2775 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2776                                      ModestWindow *win)
2777 {
2778         /* g_message ("%s %s", __FUNCTION__, link); */
2779 }
2780
2781
2782 void
2783 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2784                                         ModestWindow *win)
2785 {
2786         modest_platform_activate_uri (link);
2787 }
2788
2789 void
2790 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2791                                           ModestWindow *win)
2792 {
2793         modest_platform_show_uri_popup (link);
2794 }
2795
2796 void
2797 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2798                                              ModestWindow *win)
2799 {
2800         /* we check for low-mem; in that case, show a warning, and don't allow
2801          * viewing attachments
2802          */
2803         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2804                 return;
2805
2806         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2807 }
2808
2809 void
2810 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2811                                           const gchar *address,
2812                                           ModestWindow *win)
2813 {
2814         /* g_message ("%s %s", __FUNCTION__, address); */
2815 }
2816
2817 static void
2818 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2819                       TnyMsg *saved_draft,
2820                       gpointer user_data)
2821 {
2822         ModestMsgEditWindow *edit_window;
2823
2824         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2825 #ifndef MODEST_TOOLKIT_HILDON2
2826         ModestMainWindow *win;
2827
2828         /* FIXME. Make the header view sensitive again. This is a
2829          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2830          * for details */
2831         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2832                                          modest_runtime_get_window_mgr(), FALSE));
2833         if (win != NULL) {
2834                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2835                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2836                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2837         }
2838 #endif
2839
2840         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2841
2842         /* Set draft is there was no error */
2843         if (!modest_mail_operation_get_error (mail_op))
2844                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2845
2846         g_object_unref(edit_window);
2847 }
2848
2849 static gboolean
2850 enough_space_for_message (ModestMsgEditWindow *edit_window,
2851                           MsgData *data)
2852 {
2853         TnyAccountStore *acc_store;
2854         guint64 available_disk, expected_size;
2855         gint parts_count;
2856         guint64 parts_size;
2857
2858         /* Check size */
2859         acc_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store());
2860         available_disk = modest_utils_get_available_space (NULL);
2861         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2862         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2863                                                       data->html_body,
2864                                                       parts_count,
2865                                                       parts_size);
2866
2867         /* Double check: memory full condition or message too big */
2868         if (available_disk < MIN_FREE_SPACE ||
2869             expected_size > available_disk) {
2870                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2871                 modest_platform_information_banner (NULL, NULL, msg);
2872                 g_free (msg);
2873
2874                 return FALSE;
2875         }
2876
2877         /*
2878          * djcb: if we're in low-memory state, we only allow for
2879          * saving messages smaller than
2880          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2881          * should still allow for sending anything critical...
2882          */
2883         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2884             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2885                 return FALSE;
2886
2887         /*
2888          * djcb: we also make sure that the attachments are smaller than the max size
2889          * this is for the case where we'd try to forward a message with attachments
2890          * bigger than our max allowed size, or sending an message from drafts which
2891          * somehow got past our checks when attaching.
2892          */
2893         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2894                 modest_platform_run_information_dialog (
2895                         GTK_WINDOW(edit_window),
2896                         _KR("memr_ib_operation_disabled"),
2897                         TRUE);
2898                 return FALSE;
2899         }
2900
2901         return TRUE;
2902 }
2903
2904 gboolean
2905 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2906 {
2907         TnyTransportAccount *transport_account;
2908         ModestMailOperation *mail_operation;
2909         MsgData *data;
2910         gchar *account_name;
2911         ModestAccountMgr *account_mgr;
2912         gboolean had_error = FALSE;
2913         ModestMainWindow *win = NULL;
2914
2915         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2916
2917         data = modest_msg_edit_window_get_msg_data (edit_window);
2918
2919         /* Check size */
2920         if (!enough_space_for_message (edit_window, data)) {
2921                 modest_msg_edit_window_free_msg_data (edit_window, data);
2922                 return FALSE;
2923         }
2924
2925         account_name = g_strdup (data->account_name);
2926         account_mgr = modest_runtime_get_account_mgr();
2927         if (!account_name)
2928                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2929         if (!account_name)
2930                 account_name = modest_account_mgr_get_default_account (account_mgr);
2931         if (!account_name) {
2932                 g_printerr ("modest: no account found\n");
2933                 modest_msg_edit_window_free_msg_data (edit_window, data);
2934                 return FALSE;
2935         }
2936
2937         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2938                 account_name = g_strdup (data->account_name);
2939         }
2940
2941         transport_account =
2942                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2943                                       (modest_runtime_get_account_store (),
2944                                        account_name,
2945                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2946         if (!transport_account) {
2947                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2948                 g_free (account_name);
2949                 modest_msg_edit_window_free_msg_data (edit_window, data);
2950                 return FALSE;
2951         }
2952
2953         /* Create the mail operation */
2954         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2955                                                                         NULL, NULL);
2956         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2957
2958         modest_mail_operation_save_to_drafts (mail_operation,
2959                                               transport_account,
2960                                               data->draft_msg,
2961                                               data->from,
2962                                               data->to, 
2963                                               data->cc, 
2964                                               data->bcc,
2965                                               data->subject,
2966                                               data->plain_body,
2967                                               data->html_body,
2968                                               data->attachments,
2969                                               data->images,
2970                                               data->priority_flags,
2971                                               data->references,
2972                                               data->in_reply_to,
2973                                               on_save_to_drafts_cb,
2974                                               g_object_ref(edit_window));
2975
2976 #ifdef MODEST_TOOLKIT_HILDON2
2977         /* In hildon2 we always show the information banner on saving to drafts.
2978          * It will be a system information banner in this case.
2979          */
2980         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2981         modest_platform_information_banner (NULL, NULL, text);
2982         g_free (text);
2983 #else
2984         /* Use the main window as the parent of the banner, if the
2985            main window does not exist it won't be shown, if the parent
2986            window exists then it's properly shown. We don't use the
2987            editor window because it could be closed (save to drafts
2988            could happen after closing the window */
2989         win = (ModestMainWindow *)
2990                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2991         if (win) {
2992                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2993                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2994                 g_free (text);
2995         }
2996 #endif
2997         modest_msg_edit_window_set_modified (edit_window, FALSE);
2998
2999         /* Frees */
3000         g_free (account_name);
3001         g_object_unref (G_OBJECT (transport_account));
3002         g_object_unref (G_OBJECT (mail_operation));
3003
3004         modest_msg_edit_window_free_msg_data (edit_window, data);
3005
3006         /* ** FIXME **
3007          * If the drafts folder is selected then make the header view
3008          * insensitive while the message is being saved to drafts
3009          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3010          * is not very clean but it avoids letting the drafts folder
3011          * in an inconsistent state: the user could edit the message
3012          * being saved and undesirable things would happen.
3013          * In the average case the user won't notice anything at
3014          * all. In the worst case (the user is editing a really big
3015          * file from Drafts) the header view will be insensitive
3016          * during the saving process (10 or 20 seconds, depending on
3017          * the message). Anyway this is just a quick workaround: once
3018          * we find a better solution it should be removed
3019          * See NB#65125 (commend #18) for details.
3020          */
3021         if (!had_error && win != NULL) {
3022                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3023                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3024                 if (view != NULL) {
3025                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3026                         if (folder) {
3027                                 if (modest_tny_folder_is_local_folder(folder)) {
3028                                         TnyFolderType folder_type;
3029                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3030                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3031                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3032                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3033                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3034                                         }
3035                                 }
3036                         }
3037                         if (folder != NULL) g_object_unref(folder);
3038                 }
3039         }
3040
3041         return !had_error;
3042 }
3043
3044 /* For instance, when clicking the Send toolbar button when editing a message: */
3045 gboolean
3046 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3047 {
3048         TnyTransportAccount *transport_account = NULL;
3049         gboolean had_error = FALSE;
3050         MsgData *data;
3051         ModestAccountMgr *account_mgr;
3052         gchar *account_name;
3053         ModestMailOperation *mail_operation;
3054
3055         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3056
3057         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3058                 return TRUE;
3059
3060         data = modest_msg_edit_window_get_msg_data (edit_window);
3061
3062         /* Check size */
3063         if (!enough_space_for_message (edit_window, data)) {
3064                 modest_msg_edit_window_free_msg_data (edit_window, data);
3065                 return FALSE;
3066         }
3067
3068         account_mgr = modest_runtime_get_account_mgr();
3069         account_name = g_strdup (data->account_name);
3070         if (!account_name)
3071                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3072
3073         if (!account_name)
3074                 account_name = modest_account_mgr_get_default_account (account_mgr);
3075
3076         if (!account_name) {
3077                 modest_msg_edit_window_free_msg_data (edit_window, data);
3078                 /* Run account setup wizard */
3079                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3080                         return TRUE;
3081                 }
3082         }
3083
3084         /* Get the currently-active transport account for this modest account: */
3085         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3086                 transport_account =
3087                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3088                                               (modest_runtime_get_account_store (),
3089                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3090         }
3091
3092         if (!transport_account) {
3093                 modest_msg_edit_window_free_msg_data (edit_window, data);
3094                 /* Run account setup wizard */
3095                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3096                         return TRUE;
3097         }
3098
3099
3100         /* Create the mail operation */
3101         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3102         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3103
3104         modest_mail_operation_send_new_mail (mail_operation,
3105                                              transport_account,
3106                                              data->draft_msg,
3107                                              data->from,
3108                                              data->to,
3109                                              data->cc,
3110                                              data->bcc,
3111                                              data->subject,
3112                                              data->plain_body,
3113                                              data->html_body,
3114                                              data->attachments,
3115                                              data->images,
3116                                              data->references,
3117                                              data->in_reply_to,
3118                                              data->priority_flags);
3119
3120         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3121                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3122
3123         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3124                 const GError *error = modest_mail_operation_get_error (mail_operation);
3125                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3126                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3127                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3128                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3129                         had_error = TRUE;
3130                 }
3131         }
3132
3133         /* Free data: */
3134         g_free (account_name);
3135         g_object_unref (G_OBJECT (transport_account));
3136         g_object_unref (G_OBJECT (mail_operation));
3137
3138         modest_msg_edit_window_free_msg_data (edit_window, data);
3139
3140         if (!had_error) {
3141                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3142
3143                 /* Save settings and close the window: */
3144                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3145         }
3146
3147         return !had_error;
3148 }
3149
3150 void
3151 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3152                                   ModestMsgEditWindow *window)
3153 {
3154         ModestMsgEditFormatState *format_state = NULL;
3155
3156         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3157         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3158
3159         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3160                 return;
3161
3162         format_state = modest_msg_edit_window_get_format_state (window);
3163         g_return_if_fail (format_state != NULL);
3164
3165         format_state->bold = gtk_toggle_action_get_active (action);
3166         modest_msg_edit_window_set_format_state (window, format_state);
3167         g_free (format_state);
3168
3169 }
3170
3171 void
3172 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3173                                      ModestMsgEditWindow *window)
3174 {
3175         ModestMsgEditFormatState *format_state = NULL;
3176
3177         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3178         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3179
3180         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3181                 return;
3182
3183         format_state = modest_msg_edit_window_get_format_state (window);
3184         g_return_if_fail (format_state != NULL);
3185
3186         format_state->italics = gtk_toggle_action_get_active (action);
3187         modest_msg_edit_window_set_format_state (window, format_state);
3188         g_free (format_state);
3189
3190 }
3191
3192 void
3193 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3194                                      ModestMsgEditWindow *window)
3195 {
3196         ModestMsgEditFormatState *format_state = NULL;
3197
3198         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3199         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3200
3201         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3202                 return;
3203
3204         format_state = modest_msg_edit_window_get_format_state (window);
3205         g_return_if_fail (format_state != NULL);
3206
3207         format_state->bullet = gtk_toggle_action_get_active (action);
3208         modest_msg_edit_window_set_format_state (window, format_state);
3209         g_free (format_state);
3210
3211 }
3212
3213 void
3214 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3215                                      GtkRadioAction *selected,
3216                                      ModestMsgEditWindow *window)
3217 {
3218         ModestMsgEditFormatState *format_state = NULL;
3219         GtkJustification value;
3220
3221         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3222
3223         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3224                 return;
3225
3226         value = gtk_radio_action_get_current_value (selected);
3227
3228         format_state = modest_msg_edit_window_get_format_state (window);
3229         g_return_if_fail (format_state != NULL);
3230
3231         format_state->justification = value;
3232         modest_msg_edit_window_set_format_state (window, format_state);
3233         g_free (format_state);
3234 }
3235
3236 void
3237 modest_ui_actions_on_select_editor_color (GtkAction *action,
3238                                           ModestMsgEditWindow *window)
3239 {
3240         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3241         g_return_if_fail (GTK_IS_ACTION (action));
3242
3243         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3244                 return;
3245
3246         modest_msg_edit_window_select_color (window);
3247 }
3248
3249 void
3250 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3251                                                      ModestMsgEditWindow *window)
3252 {
3253         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3254         g_return_if_fail (GTK_IS_ACTION (action));
3255
3256         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3257                 return;
3258
3259         modest_msg_edit_window_select_background_color (window);
3260 }
3261
3262 void
3263 modest_ui_actions_on_insert_image (GObject *object,
3264                                    ModestMsgEditWindow *window)
3265 {
3266         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3267
3268
3269         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3270                 return;
3271
3272         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3273                 return;
3274
3275         modest_msg_edit_window_insert_image (window);
3276 }
3277
3278 void
3279 modest_ui_actions_on_attach_file (GtkAction *action,
3280                                   ModestMsgEditWindow *window)
3281 {
3282         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3283         g_return_if_fail (GTK_IS_ACTION (action));
3284
3285         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3286                 return;
3287
3288         modest_msg_edit_window_offer_attach_file (window);
3289 }
3290
3291 void
3292 modest_ui_actions_on_remove_attachments (GtkAction *action,
3293                                          ModestMsgEditWindow *window)
3294 {
3295         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3296
3297         modest_msg_edit_window_remove_attachments (window, NULL);
3298 }
3299
3300 static void
3301 do_create_folder_cb (ModestMailOperation *mail_op,
3302                      TnyFolderStore *parent_folder,
3303                      TnyFolder *new_folder,
3304                      gpointer user_data)
3305 {
3306         gchar *suggested_name = (gchar *) user_data;
3307         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3308         const GError *error;
3309
3310         error = modest_mail_operation_get_error (mail_op);
3311         if (error) {
3312
3313                 /* Show an error. If there was some problem writing to
3314                    disk, show it, otherwise show the generic folder
3315                    create error. We do it here and not in an error
3316                    handler because the call to do_create_folder will
3317                    stop the main loop in a gtk_dialog_run and then,
3318                    the message won't be shown until that dialog is
3319                    closed */
3320                 modest_ui_actions_disk_operations_error_handler (mail_op,
3321                                                                  _("mail_in_ui_folder_create_error"));
3322
3323                 if (!is_memory_full_error ((GError *) error, mail_op)) {
3324                         /* Try again if there is no full memory condition */
3325                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3326                 }
3327         } else {
3328                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3329                  * FIXME: any other? */
3330                 GtkWidget *folder_view;
3331
3332                 if (MODEST_IS_MAIN_WINDOW(source_win))
3333                         folder_view =
3334                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3335                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3336                 else
3337                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3338                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3339
3340                 /* Select the newly created folder. It could happen
3341                    that the widget is no longer there (i.e. the window
3342                    has been destroyed, so we need to check this */
3343                 if (folder_view)
3344                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3345                                                           new_folder, FALSE);
3346                 g_object_unref (new_folder);
3347         }
3348         /* Free. Note that the first time it'll be NULL so noop */
3349         g_free (suggested_name);
3350         g_object_unref (source_win);
3351 }
3352
3353 typedef struct {
3354         gchar *folder_name;
3355         TnyFolderStore *parent;
3356 } CreateFolderConnect;
3357
3358 static void
3359 do_create_folder_performer (gboolean canceled,
3360                          GError *err,
3361                          GtkWindow *parent_window,
3362                          TnyAccount *account,
3363                          gpointer user_data)
3364 {
3365         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3366         ModestMailOperation *mail_op;
3367
3368         if (canceled || err) {
3369                 /* In memory full conditions we could get this error here */
3370                 check_memory_full_error ((GtkWidget *) parent_window, err);
3371                 goto frees;
3372         }
3373
3374         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3375         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3376                                          mail_op);
3377         modest_mail_operation_create_folder (mail_op,
3378                                              helper->parent,
3379                                              (const gchar *) helper->folder_name,
3380                                              do_create_folder_cb,
3381                                              g_strdup (helper->folder_name));
3382         g_object_unref (mail_op);
3383
3384  frees:
3385         if (helper->parent)
3386                 g_object_unref (helper->parent);
3387         if (helper->folder_name)
3388                 g_free (helper->folder_name);
3389         g_slice_free (CreateFolderConnect, helper);
3390 }
3391
3392
3393 static void
3394 do_create_folder (GtkWindow *parent_window,
3395                   TnyFolderStore *suggested_parent,
3396                   const gchar *suggested_name)
3397 {
3398         gint result;
3399         gchar *folder_name = NULL;
3400         TnyFolderStore *parent_folder = NULL;
3401
3402         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3403                                                         suggested_parent,
3404                                                         (gchar *) suggested_name,
3405                                                         &folder_name,
3406                                                         &parent_folder);
3407
3408         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3409                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3410                 helper->folder_name = g_strdup (folder_name);
3411                 helper->parent = g_object_ref (parent_folder);
3412
3413                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3414                                                                TRUE,
3415                                                                parent_folder,
3416                                                                do_create_folder_performer,
3417                                                                helper);
3418         }
3419
3420         if (folder_name)
3421                 g_free (folder_name);
3422         if (parent_folder)
3423                 g_object_unref (parent_folder);
3424 }
3425
3426 static void
3427 modest_ui_actions_create_folder(GtkWidget *parent_window,
3428                                 GtkWidget *folder_view,
3429                                 TnyFolderStore *parent_folder)
3430 {
3431         if (!parent_folder) {
3432 #ifdef MODEST_TOOLKIT_HILDON2
3433                 ModestTnyAccountStore *acc_store;
3434
3435                 acc_store = modest_runtime_get_account_store ();
3436
3437                 parent_folder = (TnyFolderStore *)
3438                         modest_tny_account_store_get_local_folders_account (acc_store);
3439 #else
3440                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3441 #endif
3442         }
3443
3444         if (parent_folder) {
3445                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3446                 g_object_unref (parent_folder);
3447         }
3448 }
3449
3450 void
3451 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3452 {
3453
3454         g_return_if_fail (MODEST_IS_WINDOW(window));
3455
3456         if (MODEST_IS_MAIN_WINDOW (window)) {
3457                 GtkWidget *folder_view;
3458
3459                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3460                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3461                 if (!folder_view)
3462                         return;
3463
3464                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3465 #ifdef MODEST_TOOLKIT_HILDON2
3466         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3467                 GtkWidget *folder_view;
3468
3469                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3470                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3471 #endif
3472         } else {
3473                 g_assert_not_reached ();
3474         }
3475 }
3476
3477 static void
3478 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3479                                                gpointer user_data)
3480 {
3481         const GError *error = NULL;
3482         gchar *message = NULL;
3483         gboolean mem_full;
3484
3485         /* Get error message */
3486         error = modest_mail_operation_get_error (mail_op);
3487         if (!error)
3488                 g_return_if_reached ();
3489
3490         mem_full = is_memory_full_error ((GError *) error, mail_op);
3491         if (mem_full) {
3492                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3493         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3494                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3495                 message = _CS("ckdg_ib_folder_already_exists");
3496         } else if (error->domain == TNY_ERROR_DOMAIN &&
3497                    error->code == TNY_SERVICE_ERROR_STATE) {
3498                 /* This means that the folder is already in use (a
3499                    message is opened for example */
3500                 message = _("emev_ni_internal_error");
3501         } else {
3502                 message = _CS("ckdg_ib_unable_to_rename");
3503         }
3504
3505         /* We don't set a parent for the dialog because the dialog
3506            will be destroyed so the banner won't appear */
3507         modest_platform_information_banner (NULL, NULL, message);
3508
3509         if (mem_full)
3510                 g_free (message);
3511 }
3512
3513 typedef struct {
3514         TnyFolderStore *folder;
3515         gchar *new_name;
3516 } RenameFolderInfo;
3517
3518 static void
3519 on_rename_folder_cb (ModestMailOperation *mail_op,
3520                      TnyFolder *new_folder,
3521                      gpointer user_data)
3522 {
3523         ModestFolderView *folder_view;
3524
3525         /* If the window was closed when renaming a folder, or if
3526          * it's not a main window this will happen */
3527         if (!MODEST_IS_FOLDER_VIEW (user_data))
3528                 return;
3529
3530         folder_view = MODEST_FOLDER_VIEW (user_data);
3531         /* Note that if the rename fails new_folder will be NULL */
3532         if (new_folder) {
3533                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3534         } else {
3535                 modest_folder_view_select_first_inbox_or_local (folder_view);
3536         }
3537         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3538 }
3539
3540 static void
3541 on_rename_folder_performer (gboolean canceled,
3542                             GError *err,
3543                             GtkWindow *parent_window,
3544                             TnyAccount *account,
3545                             gpointer user_data)
3546 {
3547         ModestMailOperation *mail_op = NULL;
3548         GtkTreeSelection *sel = NULL;
3549         GtkWidget *folder_view = NULL;
3550         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3551
3552         if (canceled || err) {
3553                 /* In memory full conditions we could get this error here */
3554                 check_memory_full_error ((GtkWidget *) parent_window, err);
3555         } else {
3556
3557                 mail_op =
3558                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3559                                         modest_ui_actions_rename_folder_error_handler,
3560                                         parent_window, NULL);
3561
3562                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3563                                 mail_op);
3564
3565                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3566
3567                         folder_view = modest_main_window_get_child_widget (
3568                                 MODEST_MAIN_WINDOW (parent_window),
3569                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3570                 }
3571 #ifdef MODEST_TOOLKIT_HILDON2
3572                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3573                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3574                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3575                 }
3576 #endif
3577
3578                 /* Clear the folders view */
3579                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3580                 gtk_tree_selection_unselect_all (sel);
3581
3582                 /* Actually rename the folder */
3583                 modest_mail_operation_rename_folder (mail_op,
3584                                                      TNY_FOLDER (data->folder),
3585                                                      (const gchar *) (data->new_name),
3586                                                      on_rename_folder_cb,
3587                                                      folder_view);
3588                 g_object_unref (mail_op);
3589         }
3590
3591         g_object_unref (data->folder);
3592         g_free (data->new_name);
3593         g_free (data);
3594 }
3595
3596 void
3597 modest_ui_actions_on_rename_folder (GtkAction *action,
3598                                      ModestWindow *window)
3599 {
3600         modest_ui_actions_on_edit_mode_rename_folder (window);
3601 }
3602
3603 gboolean
3604 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3605 {
3606         TnyFolderStore *folder;
3607         GtkWidget *folder_view;
3608         gboolean do_rename = TRUE;
3609
3610         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3611
3612         if (MODEST_IS_MAIN_WINDOW (window)) {
3613                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3614                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3615                 if (!folder_view)
3616                         return FALSE;
3617
3618 #ifdef MODEST_TOOLKIT_HILDON2
3619         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3620                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3621 #endif
3622         } else {
3623                 return FALSE;
3624         }
3625
3626         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3627
3628         if (!folder)
3629                 return FALSE;
3630
3631         if (TNY_IS_FOLDER (folder)) {
3632                 gchar *folder_name = NULL;
3633                 gint response;
3634                 const gchar *current_name;
3635                 TnyFolderStore *parent;
3636
3637                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3638                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3639                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3640                                                                      parent, current_name,
3641                                                                      &folder_name);
3642                 g_object_unref (parent);
3643
3644                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3645                         do_rename = FALSE;
3646                 } else {
3647                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3648                         rename_folder_data->folder = g_object_ref (folder);
3649                         rename_folder_data->new_name = folder_name;
3650                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3651                                         folder, on_rename_folder_performer, rename_folder_data);
3652                 }
3653         }
3654         g_object_unref (folder);
3655         return do_rename;
3656 }
3657
3658 static void
3659 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3660                                                gpointer user_data)
3661 {
3662         GObject *win = modest_mail_operation_get_source (mail_op);
3663
3664         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3665                                                 _("mail_in_ui_folder_delete_error"),
3666                                                 FALSE);
3667         g_object_unref (win);
3668 }
3669
3670 typedef struct {
3671         TnyFolderStore *folder;
3672         gboolean move_to_trash;
3673 } DeleteFolderInfo;
3674
3675 static void
3676 on_delete_folder_cb (gboolean canceled,
3677                   GError *err,
3678                   GtkWindow *parent_window,
3679                   TnyAccount *account,
3680                   gpointer user_data)
3681 {
3682         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3683         GtkWidget *folder_view;
3684         ModestMailOperation *mail_op;
3685         GtkTreeSelection *sel;
3686
3687         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3688                 g_object_unref (G_OBJECT (info->folder));
3689                 g_free (info);
3690                 return;
3691         }
3692
3693         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3694                 folder_view = modest_main_window_get_child_widget (
3695                         MODEST_MAIN_WINDOW (parent_window),
3696                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3697 #ifdef MODEST_TOOLKIT_HILDON2
3698         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3699                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3700 #endif
3701         } else {
3702                 g_object_unref (G_OBJECT (info->folder));
3703                 g_free (info);
3704                 return;
3705         }
3706
3707         /* Unselect the folder before deleting it to free the headers */
3708         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3709         gtk_tree_selection_unselect_all (sel);
3710
3711         /* Create the mail operation */
3712         mail_op =
3713                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3714                                 modest_ui_actions_delete_folder_error_handler,
3715                                 NULL, NULL);
3716
3717         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3718                         mail_op);
3719         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3720
3721         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3722
3723         g_object_unref (G_OBJECT (mail_op));
3724         g_object_unref (G_OBJECT (info->folder));
3725         g_free (info);
3726 }
3727
3728 static gboolean
3729 delete_folder (ModestWindow *window, gboolean move_to_trash)
3730 {
3731         TnyFolderStore *folder;
3732         GtkWidget *folder_view;
3733         gint response;
3734         gchar *message;
3735
3736         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3737
3738         if (MODEST_IS_MAIN_WINDOW (window)) {
3739
3740                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3741                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3742 #ifdef MODEST_TOOLKIT_HILDON2
3743         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3744                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3745 #endif
3746         } else {
3747                 return FALSE;
3748         }
3749         if (!folder_view)
3750                 return FALSE;
3751
3752         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3753
3754         if (!folder)
3755                 return FALSE;
3756
3757         /* Show an error if it's an account */
3758         if (!TNY_IS_FOLDER (folder)) {
3759                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3760                                                         _("mail_in_ui_folder_delete_error"),
3761                                                         FALSE);
3762                 g_object_unref (G_OBJECT (folder));
3763                 return FALSE;
3764         }
3765
3766         /* Ask the user */
3767         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3768                                     tny_folder_get_name (TNY_FOLDER (folder)));
3769         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3770                                                             (const gchar *) message);
3771         g_free (message);
3772
3773         if (response == GTK_RESPONSE_OK) {
3774                 DeleteFolderInfo *info;
3775                 info = g_new0(DeleteFolderInfo, 1);
3776                 info->folder = folder;
3777                 info->move_to_trash = move_to_trash;
3778                 g_object_ref (G_OBJECT (info->folder));
3779                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3780                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3781                                                                TRUE,
3782                                                                TNY_FOLDER_STORE (account),
3783                                                                on_delete_folder_cb, info);
3784                 g_object_unref (account);
3785                 return TRUE;
3786         } else {
3787                 return FALSE;
3788         }
3789         g_object_unref (G_OBJECT (folder));
3790 }
3791
3792 void
3793 modest_ui_actions_on_delete_folder (GtkAction *action,
3794                                     ModestWindow *window)
3795 {
3796         modest_ui_actions_on_edit_mode_delete_folder (window);
3797 }
3798
3799 gboolean
3800 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3801 {
3802         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3803
3804         return delete_folder (window, FALSE);
3805 }
3806
3807 void
3808 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3809 {
3810         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3811
3812         delete_folder (MODEST_WINDOW (main_window), TRUE);
3813 }
3814
3815
3816 typedef struct _PasswordDialogFields {
3817         GtkWidget *username;
3818         GtkWidget *password;
3819         GtkWidget *dialog;
3820 } PasswordDialogFields;
3821
3822 static void
3823 password_dialog_check_field (GtkEditable *editable,
3824                              PasswordDialogFields *fields)
3825 {
3826         const gchar *value;
3827         gboolean any_value_empty = FALSE;
3828
3829 #ifdef MODEST_TOOLKIT_HILDON2
3830         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3831 #else
3832         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3833 #endif
3834         if ((value == NULL) || value[0] == '\0') {
3835                 any_value_empty = TRUE;
3836         }
3837 #ifdef MODEST_TOOLKIT_HILDON2
3838         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3839 #else
3840         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3841 #endif
3842         if ((value == NULL) || value[0] == '\0') {
3843                 any_value_empty = TRUE;
3844         }
3845         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3846 }
3847
3848 void
3849 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3850                                          const gchar* server_account_name,
3851                                          gchar **username,
3852                                          gchar **password,
3853                                          gboolean *cancel,
3854                                          gboolean *remember,
3855                                          ModestMainWindow *main_window)
3856 {
3857         g_return_if_fail(server_account_name);
3858         gboolean completed = FALSE;
3859         PasswordDialogFields *fields = NULL;
3860
3861         /* Initalize output parameters: */
3862         if (cancel)
3863                 *cancel = FALSE;
3864
3865         if (remember)
3866                 *remember = TRUE;
3867
3868 #ifndef MODEST_TOOLKIT_GTK
3869         /* Maemo uses a different (awkward) button order,
3870          * It should probably just use gtk_alternative_dialog_button_order ().
3871          */
3872 #ifdef MODEST_TOOLKIT_HILDON2
3873         GtkWidget *dialog =
3874                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3875                                              NULL,
3876                                              GTK_DIALOG_MODAL,
3877                                              _HL("wdgt_bd_done"),
3878                                              GTK_RESPONSE_ACCEPT,
3879                                              NULL);
3880         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3881                                         HILDON_MARGIN_DOUBLE);
3882 #else
3883         GtkWidget *dialog =
3884                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3885                                              NULL,
3886                                              GTK_DIALOG_MODAL,
3887                                              _("mcen_bd_dialog_ok"),
3888                                              GTK_RESPONSE_ACCEPT,
3889                                              _("mcen_bd_dialog_cancel"),
3890                                              GTK_RESPONSE_REJECT,
3891                                              NULL);
3892 #endif /* MODEST_TOOLKIT_HILDON2 */
3893 #else
3894         GtkWidget *dialog =
3895                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3896                                              NULL,
3897                                              GTK_DIALOG_MODAL,
3898                                              GTK_STOCK_CANCEL,
3899                                              GTK_RESPONSE_REJECT,
3900                                              GTK_STOCK_OK,
3901                                              GTK_RESPONSE_ACCEPT,
3902                                              NULL);
3903 #endif /* MODEST_TOOLKIT_GTK */
3904
3905         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3906
3907         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3908                 modest_runtime_get_account_mgr(), server_account_name);
3909         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3910                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3911                 if (cancel)
3912                         *cancel = TRUE;
3913                 gtk_widget_destroy (dialog);
3914                 return;
3915         }
3916
3917         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3918         GtkWidget *label = gtk_label_new (txt);
3919         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3920         g_free (txt);
3921         g_free (server_name);
3922         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3923                             FALSE, FALSE, 0);
3924         server_name = NULL;
3925
3926         /* username: */
3927         gchar *initial_username = modest_account_mgr_get_server_account_username (
3928                 modest_runtime_get_account_mgr(), server_account_name);
3929
3930 #ifdef MODEST_TOOLKIT_HILDON2
3931         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3932         if (initial_username)
3933                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
3934 #else
3935         GtkWidget *entry_username = gtk_entry_new ();
3936         if (initial_username)
3937                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3938 #endif
3939         /* Dim this if a connection has ever succeeded with this username,
3940          * as per the UI spec: */
3941         /* const gboolean username_known =  */
3942         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3943         /*              modest_runtime_get_account_mgr(), server_account_name); */
3944         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3945
3946         /* We drop the username sensitive code and disallow changing it here
3947          * as tinymail does not support really changing the username in the callback
3948          */
3949         gtk_widget_set_sensitive (entry_username, FALSE);
3950
3951 #ifndef MODEST_TOOLKIT_GTK
3952         /* Auto-capitalization is the default, so let's turn it off: */
3953         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3954
3955         /* Create a size group to be used by all captions.
3956          * Note that HildonCaption does not create a default size group if we do not specify one.
3957          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3958         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3959
3960 #ifdef MODEST_TOOLKIT_HILDON2
3961         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3962                                                                   _("mail_fi_username"), FALSE,
3963                                                                   entry_username);
3964 #else
3965         GtkWidget *caption = hildon_caption_new (sizegroup,
3966                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3967 #endif
3968         gtk_widget_show (entry_username);
3969         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3970                 FALSE, FALSE, MODEST_MARGIN_HALF);
3971         gtk_widget_show (caption);
3972 #else
3973         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3974                             TRUE, FALSE, 0);
3975 #endif /* !MODEST_TOOLKIT_GTK */
3976
3977         /* password: */
3978 #ifdef MODEST_TOOLKIT_HILDON2
3979         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3980 #else
3981         GtkWidget *entry_password = gtk_entry_new ();
3982 #endif
3983         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3984         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3985
3986 #ifndef MODEST_TOOLKIT_GTK
3987         /* Auto-capitalization is the default, so let's turn it off: */
3988         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3989                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3990
3991 #ifdef MODEST_TOOLKIT_HILDON2
3992         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3993                                                        _("mail_fi_password"), FALSE,
3994                                                        entry_password);
3995 #else
3996         caption = hildon_caption_new (sizegroup,
3997                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3998 #endif
3999         gtk_widget_show (entry_password);
4000         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4001                 FALSE, FALSE, MODEST_MARGIN_HALF);
4002         gtk_widget_show (caption);
4003         g_object_unref (sizegroup);
4004 #else
4005         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4006                             TRUE, FALSE, 0);
4007 #endif /* !MODEST_TOOLKIT_GTK */
4008
4009         if (initial_username != NULL)
4010                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4011
4012 /* This is not in the Maemo UI spec:
4013         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4014         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4015                             TRUE, FALSE, 0);
4016 */
4017
4018         fields = g_slice_new0 (PasswordDialogFields);
4019         fields->username = entry_username;
4020         fields->password = entry_password;
4021         fields->dialog = dialog;
4022
4023         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4024         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4025         password_dialog_check_field (NULL, fields);
4026
4027         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4028
4029         while (!completed) {
4030
4031                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4032                         if (username) {
4033 #ifdef MODEST_TOOLKIT_HILDON2
4034                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4035 #else
4036                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4037 #endif
4038
4039                                 /* Note that an empty field becomes the "" string */
4040                                 if (*username && strlen (*username) > 0) {
4041                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4042                                                                                         server_account_name,
4043                                                                                         *username);
4044                                         completed = TRUE;
4045
4046                                         const gboolean username_was_changed =
4047                                                 (strcmp (*username, initial_username) != 0);
4048                                         if (username_was_changed) {
4049                                                 g_warning ("%s: tinymail does not yet support changing the "
4050                                                            "username in the get_password() callback.\n", __FUNCTION__);
4051                                         }
4052                                 } else {
4053                                         g_free (*username);
4054                                         *username = NULL;
4055                                         /* Show error */
4056                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4057                                                                             _("mcen_ib_username_pw_incorrect"));
4058                                         completed = FALSE;
4059                                 }
4060                         }
4061
4062                         if (password) {
4063 #ifdef MODEST_TOOLKIT_HILDON2
4064                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4065 #else
4066                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4067 #endif
4068
4069                                 /* We do not save the password in the configuration,
4070                                  * because this function is only called for passwords that should
4071                                  * not be remembered:
4072                                  modest_server_account_set_password (
4073                                  modest_runtime_get_account_mgr(), server_account_name,
4074                                  *password);
4075                                  */
4076                         }
4077                         if (cancel)
4078                                 *cancel   = FALSE;
4079                 } else {
4080 #ifndef MODEST_TOOLKIT_HILDON2
4081                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4082                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4083 #endif
4084                         completed = TRUE;
4085                         if (username)
4086                                 *username = NULL;
4087                         if (password)
4088                                 *password = NULL;
4089                         if (cancel)
4090                                 *cancel   = TRUE;
4091                 }
4092         }
4093
4094 /* This is not in the Maemo UI spec:
4095         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4096                 *remember = TRUE;
4097         else
4098                 *remember = FALSE;
4099 */
4100
4101         g_free (initial_username);
4102         gtk_widget_destroy (dialog);
4103         g_slice_free (PasswordDialogFields, fields);
4104
4105         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4106 }
4107
4108 void
4109 modest_ui_actions_on_cut (GtkAction *action,
4110                           ModestWindow *window)
4111 {
4112         GtkWidget *focused_widget;
4113         GtkClipboard *clipboard;
4114
4115         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4116         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4117         if (GTK_IS_EDITABLE (focused_widget)) {
4118                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4119                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4120                 gtk_clipboard_store (clipboard);
4121         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4122                 GtkTextBuffer *buffer;
4123
4124                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4125                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4126                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4127                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4128                         gtk_clipboard_store (clipboard);
4129                 }
4130         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4131                 TnyList *header_list = modest_header_view_get_selected_headers (
4132                                 MODEST_HEADER_VIEW (focused_widget));
4133                 gboolean continue_download = FALSE;
4134                 gint num_of_unc_msgs;
4135
4136                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4137
4138                 if (num_of_unc_msgs) {
4139                         TnyAccount *account = get_account_from_header_list (header_list);
4140                         if (account) {
4141                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4142                                 g_object_unref (account);
4143                         }
4144                 }
4145
4146                 if (num_of_unc_msgs == 0 || continue_download) {
4147 /*                      modest_platform_information_banner (
4148                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4149                         modest_header_view_cut_selection (
4150                                         MODEST_HEADER_VIEW (focused_widget));
4151                 }
4152
4153                 g_object_unref (header_list);
4154         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4155                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4156         }
4157 }
4158
4159 void
4160 modest_ui_actions_on_copy (GtkAction *action,
4161                            ModestWindow *window)
4162 {
4163         GtkClipboard *clipboard;
4164         GtkWidget *focused_widget;
4165         gboolean copied = TRUE;
4166
4167         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4168         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4169
4170         if (GTK_IS_LABEL (focused_widget)) {
4171                 gchar *selection;
4172                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4173                 gtk_clipboard_set_text (clipboard, selection, -1);
4174                 g_free (selection);
4175                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4176                 gtk_clipboard_store (clipboard);
4177         } else if (GTK_IS_EDITABLE (focused_widget)) {
4178                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4179                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4180                 gtk_clipboard_store (clipboard);
4181         } else if (GTK_IS_HTML (focused_widget)) {
4182                 const gchar *sel;
4183                 int len = -1;
4184                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4185                 if ((sel == NULL) || (sel[0] == '\0')) {
4186                         copied = FALSE;
4187                 } else {
4188                         gtk_html_copy (GTK_HTML (focused_widget));
4189                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4190                         gtk_clipboard_store (clipboard);
4191                 }
4192         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4193                 GtkTextBuffer *buffer;
4194                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4195                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4196                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4197                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4198                         gtk_clipboard_store (clipboard);
4199                 }
4200         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4201                 TnyList *header_list = modest_header_view_get_selected_headers (
4202                                 MODEST_HEADER_VIEW (focused_widget));
4203                 gboolean continue_download = FALSE;
4204                 gint num_of_unc_msgs;
4205
4206                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4207
4208                 if (num_of_unc_msgs) {
4209                         TnyAccount *account = get_account_from_header_list (header_list);
4210                         if (account) {
4211                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4212                                 g_object_unref (account);
4213                         }
4214                 }
4215
4216                 if (num_of_unc_msgs == 0 || continue_download) {
4217                         modest_platform_information_banner (
4218                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4219                         modest_header_view_copy_selection (
4220                                         MODEST_HEADER_VIEW (focused_widget));
4221                 } else
4222                         copied = FALSE;
4223
4224                 g_object_unref (header_list);
4225
4226         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4227                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4228         }
4229
4230         /* Show information banner if there was a copy to clipboard */
4231         if(copied)
4232                 modest_platform_information_banner (
4233                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4234 }
4235
4236 void
4237 modest_ui_actions_on_undo (GtkAction *action,
4238                            ModestWindow *window)
4239 {
4240         ModestEmailClipboard *clipboard = NULL;
4241
4242         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4243                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4244         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4245                 /* Clear clipboard source */
4246                 clipboard = modest_runtime_get_email_clipboard ();
4247                 modest_email_clipboard_clear (clipboard);
4248         }
4249         else {
4250                 g_return_if_reached ();
4251         }
4252 }
4253
4254 void
4255 modest_ui_actions_on_redo (GtkAction *action,
4256                            ModestWindow *window)
4257 {
4258         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4259                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4260         }
4261         else {
4262                 g_return_if_reached ();
4263         }
4264 }
4265
4266
4267 static void
4268 destroy_information_note (ModestMailOperation *mail_op,
4269                           gpointer user_data)
4270 {
4271         /* destroy information note */
4272         gtk_widget_destroy (GTK_WIDGET(user_data));
4273 }
4274
4275 static void
4276 destroy_folder_information_note (ModestMailOperation *mail_op,
4277                                  TnyFolder *new_folder,
4278                                  gpointer user_data)
4279 {
4280         /* destroy information note */
4281         gtk_widget_destroy (GTK_WIDGET(user_data));
4282 }
4283
4284
4285 static void
4286 paste_as_attachment_free (gpointer data)
4287 {
4288         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4289
4290         if (helper->banner) {
4291                 gtk_widget_destroy (helper->banner);
4292                 g_object_unref (helper->banner);
4293         }
4294         g_free (helper);
4295 }
4296
4297 static void
4298 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4299                             TnyHeader *header,
4300                             TnyMsg *msg,
4301                             gpointer userdata)
4302 {
4303         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4304         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4305
4306         if (msg == NULL)
4307                 return;
4308
4309         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4310
4311 }
4312
4313 void
4314 modest_ui_actions_on_paste (GtkAction *action,
4315                             ModestWindow *window)
4316 {
4317         GtkWidget *focused_widget = NULL;
4318         GtkWidget *inf_note = NULL;
4319         ModestMailOperation *mail_op = NULL;
4320
4321         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4322         if (GTK_IS_EDITABLE (focused_widget)) {
4323                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4324         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4325                 ModestEmailClipboard *e_clipboard = NULL;
4326                 e_clipboard = modest_runtime_get_email_clipboard ();
4327                 if (modest_email_clipboard_cleared (e_clipboard)) {
4328                         GtkTextBuffer *buffer;
4329                         GtkClipboard *clipboard;
4330
4331                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4332                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4333                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4334                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4335                         ModestMailOperation *mail_op;
4336                         TnyFolder *src_folder = NULL;
4337                         TnyList *data = NULL;
4338                         gboolean delete;
4339                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4340                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4341                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4342                                                                            _CS("ckct_nw_pasting"));
4343                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4344                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4345                         if (helper->banner != NULL) {
4346                                 g_object_ref (G_OBJECT (helper->banner));
4347                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4348                         }
4349
4350                         if (data != NULL) {
4351                                 modest_mail_operation_get_msgs_full (mail_op,
4352                                                                      data,
4353                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4354                                                                      helper,
4355                                                                      paste_as_attachment_free);
4356                         }
4357                         /* Free */
4358                         if (data)
4359                                 g_object_unref (data);
4360                         if (src_folder)
4361                                 g_object_unref (src_folder);
4362
4363                 }
4364         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4365                 ModestEmailClipboard *clipboard = NULL;
4366                 TnyFolder *src_folder = NULL;
4367                 TnyFolderStore *folder_store = NULL;
4368                 TnyList *data = NULL;
4369                 gboolean delete = FALSE;
4370
4371                 /* Check clipboard source */
4372                 clipboard = modest_runtime_get_email_clipboard ();
4373                 if (modest_email_clipboard_cleared (clipboard))
4374                         return;
4375
4376                 /* Get elements to paste */
4377                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4378
4379                 /* Create a new mail operation */
4380                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4381
4382                 /* Get destination folder */
4383                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4384
4385                 /* transfer messages  */
4386                 if (data != NULL) {
4387                         gint response = 0;
4388
4389                         /* Ask for user confirmation */
4390                         response =
4391                                 modest_ui_actions_msgs_move_to_confirmation (window,
4392                                                                              TNY_FOLDER (folder_store),
4393                                                                              delete,
4394                                                                              data);
4395
4396                         if (response == GTK_RESPONSE_OK) {
4397                                 /* Launch notification */
4398                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4399                                                                              _CS("ckct_nw_pasting"));
4400                                 if (inf_note != NULL)  {
4401                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4402                                         gtk_widget_show (GTK_WIDGET(inf_note));
4403                                 }
4404
4405                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4406                                 modest_mail_operation_xfer_msgs (mail_op,
4407                                                                  data,
4408                                                                  TNY_FOLDER (folder_store),
4409                                                                  delete,
4410                                                                  destroy_information_note,
4411                                                                  inf_note);
4412                         } else {
4413                                 g_object_unref (mail_op);
4414                         }
4415
4416                 } else if (src_folder != NULL) {
4417                         /* Launch notification */
4418                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4419                                                                      _CS("ckct_nw_pasting"));
4420                         if (inf_note != NULL)  {
4421                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4422                                 gtk_widget_show (GTK_WIDGET(inf_note));
4423                         }
4424
4425                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4426                         modest_mail_operation_xfer_folder (mail_op,
4427                                                            src_folder,
4428                                                            folder_store,
4429                                                            delete,
4430                                                            destroy_folder_information_note,
4431                                                            inf_note);
4432                 }
4433
4434                 /* Free */
4435                 if (data != NULL)
4436                         g_object_unref (data);
4437                 if (src_folder != NULL)
4438                         g_object_unref (src_folder);
4439                 if (folder_store != NULL)
4440                         g_object_unref (folder_store);
4441         }
4442 }
4443
4444
4445 void
4446 modest_ui_actions_on_select_all (GtkAction *action,
4447                                  ModestWindow *window)
4448 {
4449         GtkWidget *focused_widget;
4450
4451         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4452         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4453                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4454         } else if (GTK_IS_LABEL (focused_widget)) {
4455                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4456         } else if (GTK_IS_EDITABLE (focused_widget)) {
4457                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4458         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4459                 GtkTextBuffer *buffer;
4460                 GtkTextIter start, end;
4461
4462                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4463                 gtk_text_buffer_get_start_iter (buffer, &start);
4464                 gtk_text_buffer_get_end_iter (buffer, &end);
4465                 gtk_text_buffer_select_range (buffer, &start, &end);
4466         } else if (GTK_IS_HTML (focused_widget)) {
4467                 gtk_html_select_all (GTK_HTML (focused_widget));
4468         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4469                 GtkWidget *header_view = focused_widget;
4470                 GtkTreeSelection *selection = NULL;
4471
4472                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4473                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4474                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4475                 }
4476
4477                 /* Disable window dimming management */
4478                 modest_window_disable_dimming (MODEST_WINDOW(window));
4479
4480                 /* Select all messages */
4481                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4482                 gtk_tree_selection_select_all (selection);
4483
4484                 /* Set focuse on header view */
4485                 gtk_widget_grab_focus (header_view);
4486
4487                 /* Enable window dimming management */
4488                 modest_window_enable_dimming (MODEST_WINDOW(window));
4489                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4490                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4491         }
4492
4493 }
4494
4495 void
4496 modest_ui_actions_on_mark_as_read (GtkAction *action,
4497                                    ModestWindow *window)
4498 {
4499         g_return_if_fail (MODEST_IS_WINDOW(window));
4500
4501         /* Mark each header as read */
4502         do_headers_action (window, headers_action_mark_as_read, NULL);
4503 }
4504
4505 void
4506 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4507                                      ModestWindow *window)
4508 {
4509         g_return_if_fail (MODEST_IS_WINDOW(window));
4510
4511         /* Mark each header as read */
4512         do_headers_action (window, headers_action_mark_as_unread, NULL);
4513 }
4514
4515 void
4516 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4517                                   GtkRadioAction *selected,
4518                                   ModestWindow *window)
4519 {
4520         gint value;
4521
4522         value = gtk_radio_action_get_current_value (selected);
4523         if (MODEST_IS_WINDOW (window)) {
4524                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4525         }
4526 }
4527
4528 void
4529 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4530                                                GtkRadioAction *selected,
4531                                                ModestWindow *window)
4532 {
4533         TnyHeaderFlags flags;
4534         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4535
4536         flags = gtk_radio_action_get_current_value (selected);
4537         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4538 }
4539
4540 void
4541 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4542                                                   GtkRadioAction *selected,
4543                                                   ModestWindow *window)
4544 {
4545         gint file_format;
4546
4547         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4548
4549         file_format = gtk_radio_action_get_current_value (selected);
4550         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4551 }
4552
4553
4554 void
4555 modest_ui_actions_on_zoom_plus (GtkAction *action,
4556                                 ModestWindow *window)
4557 {
4558         g_return_if_fail (MODEST_IS_WINDOW (window));
4559
4560         modest_window_zoom_plus (MODEST_WINDOW (window));
4561 }
4562
4563 void
4564 modest_ui_actions_on_zoom_minus (GtkAction *action,
4565                                  ModestWindow *window)
4566 {
4567         g_return_if_fail (MODEST_IS_WINDOW (window));
4568
4569         modest_window_zoom_minus (MODEST_WINDOW (window));
4570 }
4571
4572 void
4573 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4574                                            ModestWindow *window)
4575 {
4576         ModestWindowMgr *mgr;
4577         gboolean fullscreen, active;
4578         g_return_if_fail (MODEST_IS_WINDOW (window));
4579
4580         mgr = modest_runtime_get_window_mgr ();
4581
4582         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4583         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4584
4585         if (active != fullscreen) {
4586                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4587 #ifndef MODEST_TOOLKIT_HILDON2
4588                 gtk_window_present (GTK_WINDOW (window));
4589 #endif
4590         }
4591 }
4592
4593 void
4594 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4595                                         ModestWindow *window)
4596 {
4597         ModestWindowMgr *mgr;
4598         gboolean fullscreen;
4599
4600         g_return_if_fail (MODEST_IS_WINDOW (window));
4601
4602         mgr = modest_runtime_get_window_mgr ();
4603         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4604         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4605
4606 #ifndef MODEST_TOOLKIT_HILDON2
4607         gtk_window_present (GTK_WINDOW (window));
4608 #endif
4609 }
4610
4611 /*
4612  * Used by modest_ui_actions_on_details to call do_headers_action
4613  */
4614 static void
4615 headers_action_show_details (TnyHeader *header,
4616                              ModestWindow *window,
4617                              gpointer user_data)
4618
4619 {
4620         gboolean async_retrieval;
4621         TnyMsg *msg = NULL;
4622
4623         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4624                 async_retrieval = TRUE;
4625                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4626         } else {
4627                 async_retrieval = FALSE;
4628         }
4629         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4630         if (msg)
4631                 g_object_unref (msg);
4632 }
4633
4634 /*
4635  * Show the header details in a ModestDetailsDialog widget
4636  */
4637 void
4638 modest_ui_actions_on_details (GtkAction *action,
4639                               ModestWindow *win)
4640 {
4641         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4642                 TnyMsg *msg;
4643                 TnyHeader *header;
4644
4645                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4646                 if (!msg)
4647                         return;
4648
4649                 header = tny_msg_get_header (msg);
4650                 if (header) {
4651                         headers_action_show_details (header, win, NULL);
4652                         g_object_unref (header);
4653                 }
4654                 g_object_unref (msg);
4655
4656         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4657                 GtkWidget *folder_view, *header_view;
4658
4659                 /* Check which widget has the focus */
4660                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4661                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4662                 if (gtk_widget_is_focus (folder_view)) {
4663                         TnyFolderStore *folder_store
4664                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4665                         if (!folder_store) {
4666                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4667                                 return;
4668                         }
4669                         /* Show only when it's a folder */
4670                         /* This function should not be called for account items,
4671                          * because we dim the menu item for them. */
4672                         if (TNY_IS_FOLDER (folder_store)) {
4673                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4674                                                                            TNY_FOLDER (folder_store));
4675                         }
4676
4677                         g_object_unref (folder_store);
4678
4679                 } else {
4680                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4681                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4682                         /* Show details of each header */
4683                         do_headers_action (win, headers_action_show_details, header_view);
4684                 }
4685 #ifdef MODEST_TOOLKIT_HILDON2
4686         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4687                 TnyFolder *folder;
4688                 GtkWidget *header_view;
4689
4690                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4691                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4692                 if (folder) {
4693                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4694                                                                    folder);
4695                         g_object_unref (folder);
4696                 }
4697 #endif
4698         }
4699 }
4700
4701 void
4702 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4703                                      ModestMsgEditWindow *window)
4704 {
4705         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4706
4707         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4708 }
4709
4710 void
4711 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4712                                       ModestMsgEditWindow *window)
4713 {
4714         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4715
4716         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4717 }
4718
4719 void
4720 modest_ui_actions_toggle_folders_view (GtkAction *action,
4721                                        ModestMainWindow *main_window)
4722 {
4723         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4724
4725         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4726                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4727         else
4728                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4729 }
4730
4731 void
4732 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4733                                      ModestWindow *window)
4734 {
4735         gboolean active, fullscreen = FALSE;
4736         ModestWindowMgr *mgr;
4737
4738         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4739
4740         /* Check if we want to toggle the toolbar view in fullscreen
4741            or normal mode */
4742         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4743                      "ViewShowToolbarFullScreen")) {
4744                 fullscreen = TRUE;
4745         }
4746
4747         /* Toggle toolbar */
4748         mgr = modest_runtime_get_window_mgr ();
4749         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4750 }
4751
4752 void
4753 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4754                                            ModestMsgEditWindow *window)
4755 {
4756         modest_msg_edit_window_select_font (window);
4757 }
4758
4759
4760 void
4761 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4762                                                   const gchar *display_name,
4763                                                   GtkWindow *window)
4764 {
4765         /* don't update the display name if it was already set;
4766          * updating the display name apparently is expensive */
4767         const gchar* old_name = gtk_window_get_title (window);
4768
4769         if (display_name == NULL)
4770                 display_name = " ";
4771
4772         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4773                 return; /* don't do anything */
4774
4775         /* This is usually used to change the title of the main window, which
4776          * is the one that holds the folder view. Note that this change can
4777          * happen even when the widget doesn't have the focus. */
4778         gtk_window_set_title (window, display_name);
4779
4780 }
4781
4782 void
4783 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4784 {
4785         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4786         modest_msg_edit_window_select_contacts (window);
4787 }
4788
4789 void
4790 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4791 {
4792         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4793         modest_msg_edit_window_check_names (window, FALSE);
4794 }
4795
4796 #ifndef MODEST_TOOLKIT_HILDON2
4797 /*
4798  * This function is used to track changes in the selection of the
4799  * folder view that is inside the "move to" dialog to enable/disable
4800  * the OK button because we do not want the user to select a disallowed
4801  * destination for a folder.
4802  * The user also not desired to be able to use NEW button on items where
4803  * folder creation is not possibel.
4804  */
4805 static void
4806 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4807                                             TnyFolderStore *folder_store,
4808                                             gboolean selected,
4809                                             gpointer user_data)
4810 {
4811         GtkWidget *dialog = NULL;
4812         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4813         gboolean moving_folder = FALSE;
4814         gboolean is_local_account = TRUE;
4815         GtkWidget *folder_view = NULL;
4816         ModestTnyFolderRules rules;
4817
4818         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4819
4820         if (!selected)
4821                 return;
4822
4823         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4824         if (!dialog)
4825                 return;
4826
4827         /* check if folder_store is an remote account */
4828         if (TNY_IS_ACCOUNT (folder_store)) {
4829                 TnyAccount *local_account = NULL;
4830                 TnyAccount *mmc_account = NULL;
4831                 ModestTnyAccountStore *account_store = NULL;
4832
4833                 account_store = modest_runtime_get_account_store ();
4834                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4835                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4836
4837                 if ((gpointer) local_account != (gpointer) folder_store &&
4838                     (gpointer) mmc_account != (gpointer) folder_store) {
4839                         ModestProtocolType proto;
4840                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4841                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4842                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4843                         }
4844                         is_local_account = FALSE;
4845                         /* New button should be dimmed on remote
4846                            POP account root */
4847                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4848                                                                                          proto,
4849                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4850                 }
4851                 g_object_unref (local_account);
4852
4853                 /* It could not exist */
4854                 if (mmc_account)
4855                         g_object_unref (mmc_account);
4856         }
4857
4858         /* Check the target folder rules */
4859         if (TNY_IS_FOLDER (folder_store)) {
4860                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4861                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4862                         ok_sensitive = FALSE;
4863                         new_sensitive = FALSE;
4864                         goto end;
4865                 }
4866         }
4867
4868         /* Check if we're moving a folder */
4869         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4870                 /* Get the widgets */
4871                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4872                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4873                 if (gtk_widget_is_focus (folder_view))
4874                         moving_folder = TRUE;
4875         }
4876
4877         if (moving_folder) {
4878                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4879
4880                 /* Get the folder to move */
4881                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4882
4883                 /* Check that we're not moving to the same folder */
4884                 if (TNY_IS_FOLDER (moved_folder)) {
4885                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4886                         if (parent == folder_store)
4887                                 ok_sensitive = FALSE;
4888                         g_object_unref (parent);
4889                 }
4890
4891                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4892                         /* Do not allow to move to an account unless it's the
4893                            local folders account */
4894                         if (!is_local_account)
4895                                 ok_sensitive = FALSE;
4896                 }
4897
4898                 if (ok_sensitive && (moved_folder == folder_store)) {
4899                         /* Do not allow to move to itself */
4900                         ok_sensitive = FALSE;
4901                 }
4902                 g_object_unref (moved_folder);
4903         } else {
4904                 TnyFolder *src_folder = NULL;
4905
4906                 /* Moving a message */
4907                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4908
4909                         TnyHeader *header = NULL;
4910                         header = modest_msg_view_window_get_header
4911                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4912                         if (!TNY_IS_HEADER(header))
4913                                 g_warning ("%s: could not get source header", __FUNCTION__);
4914                         else
4915                                 src_folder = tny_header_get_folder (header);
4916
4917                         if (header)
4918                                 g_object_unref (header);
4919                 } else {
4920                         src_folder =
4921                                 TNY_FOLDER (modest_folder_view_get_selected
4922                                             (MODEST_FOLDER_VIEW (folder_view)));
4923                 }
4924
4925                 if (TNY_IS_FOLDER(src_folder)) {
4926                         /* Do not allow to move the msg to the same folder */
4927                         /* Do not allow to move the msg to an account */
4928                         if ((gpointer) src_folder == (gpointer) folder_store ||
4929                             TNY_IS_ACCOUNT (folder_store))
4930                                 ok_sensitive = FALSE;
4931                         g_object_unref (src_folder);
4932                 } else
4933                         g_warning ("%s: could not get source folder", __FUNCTION__);
4934         }
4935
4936  end:
4937         /* Set sensitivity of the OK and NEW button */
4938         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
4939         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
4940 }
4941 #endif
4942
4943 static void
4944 on_move_to_dialog_response (GtkDialog *dialog,
4945                             gint       response,
4946                             gpointer   user_data)
4947 {
4948         GtkWidget *parent_win;
4949         MoveToInfo *helper = NULL;
4950         ModestFolderView *folder_view;
4951
4952         helper = (MoveToInfo *) user_data;
4953
4954         parent_win = (GtkWidget *) helper->win;
4955         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4956                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4957
4958         switch (response) {
4959                 TnyFolderStore *dst_folder;
4960                 TnyFolderStore *selected;
4961
4962         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4963                 selected = modest_folder_view_get_selected (folder_view);
4964                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
4965                 g_object_unref (selected);
4966                 return;
4967         case GTK_RESPONSE_NONE:
4968         case GTK_RESPONSE_CANCEL:
4969         case GTK_RESPONSE_DELETE_EVENT:
4970                 break;
4971         case GTK_RESPONSE_OK:
4972                 dst_folder = modest_folder_view_get_selected (folder_view);
4973
4974                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
4975                         /* Clean list to move used for filtering */
4976                         modest_folder_view_set_list_to_move (folder_view, NULL);
4977
4978                         modest_ui_actions_on_main_window_move_to (NULL,
4979                                                                   GTK_WIDGET (folder_view),
4980                                                                   dst_folder,
4981                                                                   MODEST_MAIN_WINDOW (parent_win));
4982 #ifdef MODEST_TOOLKIT_HILDON2
4983                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4984                         /* Clean list to move used for filtering */
4985                         modest_folder_view_set_list_to_move (folder_view, NULL);
4986
4987                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4988                                                                     dst_folder,
4989                                                                     helper->list,
4990                                                                     GTK_WINDOW (parent_win));
4991 #endif
4992                 } else {
4993                         /* if the user selected a root folder
4994                            (account) then do not perform any action */
4995                         if (TNY_IS_ACCOUNT (dst_folder)) {
4996                                 g_signal_stop_emission_by_name (dialog, "response");
4997                                 return;
4998                         }
4999
5000                         /* Clean list to move used for filtering */
5001                         modest_folder_view_set_list_to_move (folder_view, NULL);
5002
5003                         /* Moving from headers window in edit mode */
5004                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5005                                                              dst_folder,
5006                                                              MODEST_WINDOW (parent_win));
5007                 }
5008
5009                 if (dst_folder)
5010                         g_object_unref (dst_folder);
5011
5012                 break;
5013         default:
5014                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5015         }
5016
5017         /* Free the helper and exit */
5018         if (helper->list)
5019                 g_object_unref (helper->list);
5020         g_slice_free (MoveToInfo, helper);
5021         gtk_widget_destroy (GTK_WIDGET (dialog));
5022 }
5023
5024 static GtkWidget*
5025 create_move_to_dialog (GtkWindow *win,
5026                        GtkWidget *folder_view,
5027                        TnyList *list_to_move)
5028 {
5029         GtkWidget *dialog, *tree_view = NULL;
5030
5031         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5032
5033 #ifndef MODEST_TOOLKIT_HILDON2
5034         /* Track changes in the selection to
5035          * disable the OK button whenever "Move to" is not possible
5036          * disbale NEW button whenever New is not possible */
5037         g_signal_connect (tree_view,
5038                           "folder_selection_changed",
5039                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5040                           win);
5041 #endif
5042
5043         /* It could happen that we're trying to move a message from a
5044            window (msg window for example) after the main window was
5045            closed, so we can not just get the model of the folder
5046            view */
5047         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5048                 const gchar *visible_id = NULL;
5049
5050                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5051                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5052                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5053                                                MODEST_FOLDER_VIEW(tree_view));
5054
5055                 visible_id =
5056                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5057
5058                 /* Show the same account than the one that is shown in the main window */
5059                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5060                                                                              visible_id);
5061         } else {
5062                 const gchar *active_account_name = NULL;
5063                 ModestAccountMgr *mgr = NULL;
5064                 ModestAccountSettings *settings = NULL;
5065                 ModestServerAccountSettings *store_settings = NULL;
5066
5067                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5068                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5069                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5070                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5071
5072                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5073                 mgr = modest_runtime_get_account_mgr ();
5074                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5075
5076                 if (settings) {
5077                         const gchar *store_account_name;
5078                         store_settings = modest_account_settings_get_store_settings (settings);
5079                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5080
5081                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5082                                                                                      store_account_name);
5083                         g_object_unref (store_settings);
5084                         g_object_unref (settings);
5085                 }
5086         }
5087
5088         /* we keep a pointer to the embedded folder view, so we can
5089          *   retrieve it with get_folder_view_from_move_to_dialog (see
5090          *   above) later (needed for focus handling)
5091          */
5092         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5093
5094         /* Hide special folders */
5095 #ifndef MODEST_TOOLKIT_HILDON2
5096         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5097 #endif
5098         if (list_to_move)
5099                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5100 #ifndef MODEST_TOOLKIT_HILDON2
5101         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5102 #endif
5103
5104         gtk_widget_show (GTK_WIDGET (tree_view));
5105
5106         return dialog;
5107 }
5108
5109 /*
5110  * Shows a confirmation dialog to the user when we're moving messages
5111  * from a remote server to the local storage. Returns the dialog
5112  * response. If it's other kind of movement then it always returns
5113  * GTK_RESPONSE_OK
5114  *
5115  * This one is used by the next functions:
5116  *      modest_ui_actions_on_paste                      - commented out
5117  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5118  */
5119 gint
5120 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5121                                              TnyFolder *dest_folder,
5122                                              gboolean delete,
5123                                              TnyList *headers)
5124 {
5125         gint response = GTK_RESPONSE_OK;
5126         TnyAccount *account = NULL;
5127         TnyFolder *src_folder = NULL;
5128         TnyIterator *iter = NULL;
5129         TnyHeader *header = NULL;
5130
5131         /* return with OK if the destination is a remote folder */
5132         if (modest_tny_folder_is_remote_folder (dest_folder))
5133                 return GTK_RESPONSE_OK;
5134
5135         /* Get source folder */
5136         iter = tny_list_create_iterator (headers);
5137         header = TNY_HEADER (tny_iterator_get_current (iter));
5138         if (header) {
5139                 src_folder = tny_header_get_folder (header);
5140                 g_object_unref (header);
5141         }
5142         g_object_unref (iter);
5143
5144         /* if no src_folder, message may be an attahcment */
5145         if (src_folder == NULL)
5146                 return GTK_RESPONSE_CANCEL;
5147
5148         /* If the source is a local or MMC folder */
5149         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5150                 g_object_unref (src_folder);
5151                 return GTK_RESPONSE_OK;
5152         }
5153
5154         /* Get the account */
5155         account = tny_folder_get_account (src_folder);
5156
5157         /* now if offline we ask the user */
5158         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5159                 response = GTK_RESPONSE_OK;
5160         else
5161                 response = GTK_RESPONSE_CANCEL;
5162
5163         /* Frees */
5164         g_object_unref (src_folder);
5165         g_object_unref (account);
5166
5167         return response;
5168 }
5169
5170 static void
5171 move_to_helper_destroyer (gpointer user_data)
5172 {
5173         MoveToHelper *helper = (MoveToHelper *) user_data;
5174
5175         /* Close the "Pasting" information banner */
5176         if (helper->banner) {
5177                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5178                 g_object_unref (helper->banner);
5179         }
5180         if (gtk_tree_row_reference_valid (helper->reference)) {
5181                 gtk_tree_row_reference_free (helper->reference);
5182                 helper->reference = NULL;
5183         }
5184         g_free (helper);
5185 }
5186
5187 static void
5188 move_to_cb (ModestMailOperation *mail_op,
5189             gpointer user_data)
5190 {
5191         MoveToHelper *helper = (MoveToHelper *) user_data;
5192         GObject *object = modest_mail_operation_get_source (mail_op);
5193
5194         /* Note that the operation could have failed, in that case do
5195            nothing */
5196         if (modest_mail_operation_get_status (mail_op) !=
5197             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5198                 goto frees;
5199
5200         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5201                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5202
5203                 if (!modest_msg_view_window_select_next_message (self) &&
5204                     !modest_msg_view_window_select_previous_message (self)) {
5205                         /* No more messages to view, so close this window */
5206                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5207                 }
5208         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5209                    gtk_tree_row_reference_valid (helper->reference)) {
5210                 GtkWidget *header_view;
5211                 GtkTreePath *path;
5212                 GtkTreeSelection *sel;
5213
5214                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5215                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5216                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5217                 path = gtk_tree_row_reference_get_path (helper->reference);
5218                 /* We need to unselect the previous one
5219                    because we could be copying instead of
5220                    moving */
5221                 gtk_tree_selection_unselect_all (sel);
5222                 gtk_tree_selection_select_path (sel, path);
5223                 gtk_tree_path_free (path);
5224         }
5225         g_object_unref (object);
5226
5227  frees:
5228         /* Destroy the helper */
5229         move_to_helper_destroyer (helper);
5230 }
5231
5232 static void
5233 folder_move_to_cb (ModestMailOperation *mail_op,
5234                    TnyFolder *new_folder,
5235                    gpointer user_data)
5236 {
5237         GtkWidget *folder_view;
5238         GObject *object;
5239
5240         object = modest_mail_operation_get_source (mail_op);
5241         if (MODEST_IS_MAIN_WINDOW (object)) {
5242                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5243                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5244                 g_object_ref (folder_view);
5245                 g_object_unref (object);
5246                 move_to_cb (mail_op, user_data);
5247                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5248                 g_object_unref (folder_view);
5249         } else {
5250                 move_to_cb (mail_op, user_data);
5251         }
5252 }
5253
5254 static void
5255 msgs_move_to_cb (ModestMailOperation *mail_op,
5256                  gpointer user_data)
5257 {
5258         move_to_cb (mail_op, user_data);
5259 }
5260
5261 void
5262 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5263                                              gpointer user_data)
5264 {
5265         GObject *win = NULL;
5266
5267 #ifndef MODEST_TOOLKIT_HILDON2
5268         ModestWindow *main_window = NULL;
5269
5270         /* Disable next automatic folder selection */
5271         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5272                                                          FALSE); /* don't create */
5273         if (main_window) {
5274                 GtkWidget *folder_view = NULL;
5275
5276                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5277                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5278                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5279
5280                 if (user_data && TNY_IS_FOLDER (user_data)) {
5281                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5282                                                           TNY_FOLDER (user_data), FALSE);
5283                 }
5284         }
5285 #endif
5286         /* Show notification dialog only if the main window exists */
5287         win = modest_mail_operation_get_source (mail_op);
5288         modest_platform_run_information_dialog ((GtkWindow *) win,
5289                                                 _("mail_in_ui_folder_move_target_error"),
5290                                                 FALSE);
5291         if (win)
5292                 g_object_unref (win);
5293 }
5294
5295 static void
5296 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5297                        TnyHeader *header,
5298                        gboolean canceled,
5299                        TnyMsg *msg,
5300                        GError *err,
5301                        gpointer user_data)
5302 {
5303         TnyList *parts;
5304         TnyIterator *iter;
5305         gint pending_purges = 0;
5306         gboolean some_purged = FALSE;
5307         ModestWindow *win = MODEST_WINDOW (user_data);
5308         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5309
5310         /* If there was any error */
5311         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5312                 modest_window_mgr_unregister_header (mgr, header);
5313                 return;
5314         }
5315
5316         /* Once the message has been retrieved for purging, we check if
5317          * it's all ok for purging */
5318
5319         parts = tny_simple_list_new ();
5320         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5321         iter = tny_list_create_iterator (parts);
5322
5323         while (!tny_iterator_is_done (iter)) {
5324                 TnyMimePart *part;
5325                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5326                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5327                         if (tny_mime_part_is_purged (part))
5328                                 some_purged = TRUE;
5329                         else
5330                                 pending_purges++;
5331                 }
5332
5333                 if (part)
5334                         g_object_unref (part);
5335
5336                 tny_iterator_next (iter);
5337         }
5338         g_object_unref (iter);
5339
5340
5341         if (pending_purges>0) {
5342                 gint response;
5343                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5344
5345                 if (response == GTK_RESPONSE_OK) {
5346                         GtkWidget *info;
5347                         info =
5348                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5349                         iter = tny_list_create_iterator (parts);
5350                         while (!tny_iterator_is_done (iter)) {
5351                                 TnyMimePart *part;
5352
5353                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5354                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5355                                         tny_mime_part_set_purged (part);
5356
5357                                 if (part)
5358                                         g_object_unref (part);
5359
5360                                 tny_iterator_next (iter);
5361                         }
5362                         g_object_unref (iter);
5363
5364                         tny_msg_rewrite_cache (msg);
5365
5366                         gtk_widget_destroy (info);
5367                 }
5368         }
5369
5370         modest_window_mgr_unregister_header (mgr, header);
5371
5372         g_object_unref (parts);
5373 }
5374
5375 static void
5376 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5377                                                      ModestMainWindow *win)
5378 {
5379         GtkWidget *header_view;
5380         TnyList *header_list;
5381         TnyHeader *header;
5382         TnyHeaderFlags flags;
5383         ModestWindow *msg_view_window =  NULL;
5384         gboolean found;
5385
5386         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5387
5388         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5389                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5390
5391         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5392         if (!header_list) {
5393                 g_warning ("%s: no header selected", __FUNCTION__);
5394                 return;
5395         }
5396
5397         if (tny_list_get_length (header_list) == 1) {
5398                 TnyIterator *iter = tny_list_create_iterator (header_list);
5399                 header = TNY_HEADER (tny_iterator_get_current (iter));
5400                 g_object_unref (iter);
5401         } else
5402                 return;
5403
5404         if (!header || !TNY_IS_HEADER(header)) {
5405                 g_warning ("%s: header is not valid", __FUNCTION__);
5406                 return;
5407         }
5408
5409         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5410                                                           header, &msg_view_window);
5411         flags = tny_header_get_flags (header);
5412         if (!(flags & TNY_HEADER_FLAG_CACHED))
5413                 return;
5414         if (found) {
5415                 if (msg_view_window != NULL)
5416                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5417                 else {
5418                         /* do nothing; uid was registered before, so window is probably on it's way */
5419                         g_warning ("debug: header %p has already been registered", header);
5420                 }
5421         } else {
5422                 ModestMailOperation *mail_op = NULL;
5423                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5424                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5425                                                                          modest_ui_actions_disk_operations_error_handler,
5426                                                                          NULL, NULL);
5427                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5428                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5429
5430                 g_object_unref (mail_op);
5431         }
5432         if (header)
5433                 g_object_unref (header);
5434         if (header_list)
5435                 g_object_unref (header_list);
5436 }
5437
5438 /*
5439  * Checks if we need a connection to do the transfer and if the user
5440  * wants to connect to complete it
5441  */
5442 static void
5443 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5444                                        TnyFolderStore *src_folder,
5445                                        TnyList *headers,
5446                                        TnyFolder *dst_folder,
5447                                        gboolean delete_originals,
5448                                        gboolean *need_connection,
5449                                        gboolean *do_xfer)
5450 {
5451         TnyAccount *src_account;
5452         gint uncached_msgs = 0;
5453
5454         /* We don't need any further check if
5455          *
5456          * 1- the source folder is local OR
5457          * 2- the device is already online
5458          */
5459         if (!modest_tny_folder_store_is_remote (src_folder) ||
5460             tny_device_is_online (modest_runtime_get_device())) {
5461                 *need_connection = FALSE;
5462                 *do_xfer = TRUE;
5463                 return;
5464         }
5465
5466         /* We must ask for a connection when
5467          *
5468          *   - the message(s) is not already cached   OR
5469          *   - the message(s) is cached but the leave_on_server setting
5470          * is FALSE (because we need to sync the source folder to
5471          * delete the message from the server (for IMAP we could do it
5472          * offline, it'll take place the next time we get a
5473          * connection)
5474          */
5475         uncached_msgs = header_list_count_uncached_msgs (headers);
5476         src_account = get_account_from_folder_store (src_folder);
5477         if (uncached_msgs > 0) {
5478                 guint num_headers;
5479                 const gchar *msg;
5480
5481                 *need_connection = TRUE;
5482                 num_headers = tny_list_get_length (headers);
5483                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5484
5485                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5486                     GTK_RESPONSE_CANCEL) {
5487                         *do_xfer = FALSE;
5488                 } else {
5489                         *do_xfer = TRUE;
5490                 }
5491         } else {
5492                 /* The transfer is possible and the user wants to */
5493                 *do_xfer = TRUE;
5494
5495                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5496                         const gchar *account_name;
5497                         gboolean leave_on_server;
5498
5499                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5500                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5501                                                                                   account_name);
5502
5503                         if (leave_on_server == TRUE) {
5504                                 *need_connection = FALSE;
5505                         } else {
5506                                 *need_connection = TRUE;
5507                         }
5508                 } else {
5509                         *need_connection = FALSE;
5510                 }
5511         }
5512
5513         /* Frees */
5514         g_object_unref (src_account);
5515 }
5516
5517 static void
5518 xfer_messages_error_handler (ModestMailOperation *mail_op,
5519                              gpointer user_data)
5520 {
5521         GObject *win;
5522         const GError *error;
5523
5524         win = modest_mail_operation_get_source (mail_op);
5525         error = modest_mail_operation_get_error (mail_op);
5526
5527         if (error && is_memory_full_error ((GError *) error, mail_op)) {
5528                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
5529                 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
5530                 g_free (msg);
5531         } else {
5532                 modest_platform_run_information_dialog ((GtkWindow *) win,
5533                                                         _("mail_in_ui_folder_move_target_error"),
5534                                                         FALSE);
5535         }
5536         if (win)
5537                 g_object_unref (win);
5538 }
5539
5540 typedef struct {
5541         TnyFolderStore *dst_folder;
5542         TnyList *headers;
5543 } XferMsgsHelper;
5544
5545 /**
5546  * Utility function that transfer messages from both the main window
5547  * and the msg view window when using the "Move to" dialog
5548  */
5549 static void
5550 xfer_messages_performer  (gboolean canceled,
5551                           GError *err,
5552                           GtkWindow *parent_window,
5553                           TnyAccount *account,
5554                           gpointer user_data)
5555 {
5556         ModestWindow *win = MODEST_WINDOW (parent_window);
5557         TnyAccount *dst_account = NULL;
5558         gboolean dst_forbids_message_add = FALSE;
5559         XferMsgsHelper *helper;
5560         MoveToHelper *movehelper;
5561         ModestMailOperation *mail_op;
5562
5563         helper = (XferMsgsHelper *) user_data;
5564
5565         if (canceled || err) {
5566                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5567                         /* Show the proper error message */
5568                         modest_ui_actions_on_account_connection_error (parent_window, account);
5569                 }
5570                 goto end;
5571         }
5572
5573         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5574
5575         /* tinymail will return NULL for local folders it seems */
5576         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5577                                                                                   modest_tny_account_get_protocol_type (dst_account),
5578                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5579         g_object_unref (dst_account);
5580
5581         if (dst_forbids_message_add) {
5582                 modest_platform_information_banner (GTK_WIDGET (win),
5583                                                     NULL,
5584                                                     ngettext("mail_in_ui_folder_move_target_error",
5585                                                              "mail_in_ui_folder_move_targets_error",
5586                                                              tny_list_get_length (helper->headers)));
5587                 goto end;
5588         }
5589
5590         movehelper = g_new0 (MoveToHelper, 1);
5591
5592 #ifndef MODEST_TOOLKIT_HILDON2
5593         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5594                                                                _CS("ckct_nw_pasting"));
5595         if (movehelper->banner != NULL)  {
5596                 g_object_ref (movehelper->banner);
5597                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5598         }
5599 #endif
5600
5601         if (MODEST_IS_MAIN_WINDOW (win)) {
5602                 GtkWidget *header_view =
5603                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5604                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5605                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5606         }
5607
5608         /* Perform the mail operation */
5609         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5610                                                                  xfer_messages_error_handler,
5611                                                                  movehelper, NULL);
5612         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5613                                          mail_op);
5614
5615         modest_mail_operation_xfer_msgs (mail_op,
5616                                          helper->headers,
5617                                          TNY_FOLDER (helper->dst_folder),
5618                                          TRUE,
5619                                          msgs_move_to_cb,
5620                                          movehelper);
5621
5622         g_object_unref (G_OBJECT (mail_op));
5623  end:
5624         g_object_unref (helper->dst_folder);
5625         g_object_unref (helper->headers);
5626         g_slice_free (XferMsgsHelper, helper);
5627 }
5628
5629 typedef struct {
5630         TnyFolder *src_folder;
5631         TnyFolderStore *dst_folder;
5632         gboolean delete_original;
5633         GtkWidget *folder_view;
5634 } MoveFolderInfo;
5635
5636 static void
5637 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5638                 TnyAccount *account, gpointer user_data)
5639 {
5640         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5641         GtkTreeSelection *sel;
5642         ModestMailOperation *mail_op = NULL;
5643
5644         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5645                 g_object_unref (G_OBJECT (info->src_folder));
5646                 g_object_unref (G_OBJECT (info->dst_folder));
5647                 g_free (info);
5648                 return;
5649         }
5650
5651         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5652 #ifndef MODEST_TOOLKIT_HILDON2
5653         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5654                         _CS("ckct_nw_pasting"));
5655         if (helper->banner != NULL)  {
5656                 g_object_ref (helper->banner);
5657                 gtk_widget_show (GTK_WIDGET(helper->banner));
5658         }
5659 #endif
5660         /* Clean folder on header view before moving it */
5661         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5662         gtk_tree_selection_unselect_all (sel);
5663
5664         /* Let gtk events run. We need that the folder
5665            view frees its reference to the source
5666            folder *before* issuing the mail operation
5667            so we need the signal handler of selection
5668            changed to happen before the mail
5669            operation
5670         while (gtk_events_pending ())
5671                 gtk_main_iteration ();   */
5672
5673         mail_op =
5674                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5675                                 modest_ui_actions_move_folder_error_handler,
5676                                 info->src_folder, NULL);
5677         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5678                         mail_op);
5679
5680         /* Select *after* the changes */
5681         /* TODO: this function hangs UI after transfer */
5682         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5683         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5684
5685         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5686                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5687                                                   TNY_FOLDER (info->dst_folder), TRUE);
5688         }
5689         modest_mail_operation_xfer_folder (mail_op,
5690                         TNY_FOLDER (info->src_folder),
5691                         info->dst_folder,
5692                         info->delete_original,
5693                         folder_move_to_cb,
5694                         helper);
5695         g_object_unref (G_OBJECT (info->src_folder));
5696
5697         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5698         /* } */
5699
5700         /* Unref mail operation */
5701         g_object_unref (G_OBJECT (mail_op));
5702         g_object_unref (G_OBJECT (info->dst_folder));
5703         g_free (user_data);
5704 }
5705
5706 static TnyAccount *
5707 get_account_from_folder_store (TnyFolderStore *folder_store)
5708 {
5709         if (TNY_IS_ACCOUNT (folder_store))
5710                 return g_object_ref (folder_store);
5711         else
5712                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5713 }
5714
5715 /*
5716  * UI handler for the "Move to" action when invoked from the
5717  * ModestMainWindow
5718  */
5719 static void
5720 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5721                                           GtkWidget *folder_view,
5722                                           TnyFolderStore *dst_folder,
5723                                           ModestMainWindow *win)
5724 {
5725         ModestHeaderView *header_view = NULL;
5726         TnyFolderStore *src_folder = NULL;
5727
5728         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5729
5730         /* Get the source folder */
5731         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5732
5733         /* Get header view */
5734         header_view = (ModestHeaderView *)
5735                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5736
5737         /* Get folder or messages to transfer */
5738         if (gtk_widget_is_focus (folder_view)) {
5739                 gboolean do_xfer = TRUE;
5740
5741                 /* Allow only to transfer folders to the local root folder */
5742                 if (TNY_IS_ACCOUNT (dst_folder) &&
5743                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5744                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5745                         do_xfer = FALSE;
5746                 } else if (!TNY_IS_FOLDER (src_folder)) {
5747                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5748                         do_xfer = FALSE;
5749                 }
5750
5751                 if (do_xfer) {
5752                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5753                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5754
5755                         info->src_folder = g_object_ref (src_folder);
5756                         info->dst_folder = g_object_ref (dst_folder);
5757                         info->delete_original = TRUE;
5758                         info->folder_view = folder_view;
5759
5760                         connect_info->callback = on_move_folder_cb;
5761                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5762                         connect_info->data = info;
5763
5764                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5765                                                                    TNY_FOLDER_STORE (src_folder),
5766                                                                    connect_info);
5767                 }
5768         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5769                 TnyList *headers;
5770
5771                 headers = modest_header_view_get_selected_headers(header_view);
5772
5773                 /* Transfer the messages */
5774                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5775                                                             headers, TNY_FOLDER (dst_folder));
5776
5777                 g_object_unref (headers);
5778         }
5779
5780         /* Frees */
5781         g_object_unref (src_folder);
5782 }
5783
5784 #ifdef MODEST_TOOLKIT_HILDON2
5785 /*
5786  * UI handler for the "Move to" action when invoked from the
5787  * ModestFolderWindow
5788  */
5789 static void
5790 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5791                                             TnyFolderStore *dst_folder,
5792                                             TnyList *selection,
5793                                             GtkWindow *win)
5794 {
5795         TnyFolderStore *src_folder = NULL;
5796         TnyIterator *iterator;
5797
5798         if (tny_list_get_length (selection) != 1)
5799                 return;
5800
5801         iterator = tny_list_create_iterator (selection);
5802         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5803         g_object_unref (iterator);
5804
5805
5806         gboolean do_xfer = TRUE;
5807
5808         /* Allow only to transfer folders to the local root folder */
5809         if (TNY_IS_ACCOUNT (dst_folder) &&
5810             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5811             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5812                 do_xfer = FALSE;
5813                 /* Show an error */
5814                 modest_platform_run_information_dialog (win,
5815                                                         _("mail_in_ui_folder_move_target_error"),
5816                                                         FALSE);
5817         } else if (!TNY_IS_FOLDER (src_folder)) {
5818                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5819                 do_xfer = FALSE;
5820         }
5821
5822         if (do_xfer) {
5823                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5824                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5825
5826                 info->src_folder = g_object_ref (src_folder);
5827                 info->dst_folder = g_object_ref (dst_folder);
5828                 info->delete_original = TRUE;
5829                 info->folder_view = folder_view;
5830
5831                 connect_info->callback = on_move_folder_cb;
5832                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5833                 connect_info->data = info;
5834
5835                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5836                                                            TNY_FOLDER_STORE (src_folder),
5837                                                            connect_info);
5838         }
5839
5840         /* Frees */
5841         g_object_unref (src_folder);
5842 }
5843 #endif
5844
5845
5846 void
5847 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5848                                             TnyFolder *src_folder,
5849                                             TnyList *headers,
5850                                             TnyFolder *dst_folder)
5851 {
5852         gboolean need_connection = TRUE;
5853         gboolean do_xfer = TRUE;
5854         XferMsgsHelper *helper;
5855
5856         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5857         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5858         g_return_if_fail (TNY_IS_LIST (headers));
5859
5860         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5861                                                headers, TNY_FOLDER (dst_folder),
5862                                                TRUE, &need_connection,
5863                                                &do_xfer);
5864
5865         /* If we don't want to transfer just return */
5866         if (!do_xfer)
5867                 return;
5868
5869         /* Create the helper */
5870         helper = g_slice_new (XferMsgsHelper);
5871         helper->dst_folder = g_object_ref (dst_folder);
5872         helper->headers = g_object_ref (headers);
5873
5874         if (need_connection) {
5875                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5876                 connect_info->callback = xfer_messages_performer;
5877                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5878                 connect_info->data = helper;
5879
5880                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5881                                                            TNY_FOLDER_STORE (src_folder),
5882                                                            connect_info);
5883         } else {
5884                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5885                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5886                                          src_account, helper);
5887                 g_object_unref (src_account);
5888         }
5889 }
5890
5891 /*
5892  * UI handler for the "Move to" action when invoked from the
5893  * ModestMsgViewWindow
5894  */
5895 static void
5896 modest_ui_actions_on_window_move_to (GtkAction *action,
5897                                      TnyList *headers,
5898                                      TnyFolderStore *dst_folder,
5899                                      ModestWindow *win)
5900 {
5901         TnyFolder *src_folder = NULL;
5902
5903         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5904
5905         if (headers) {
5906                 TnyHeader *header = NULL;
5907                 TnyIterator *iter;
5908
5909                 iter = tny_list_create_iterator (headers);
5910                 header = (TnyHeader *) tny_iterator_get_current (iter);
5911                 src_folder = tny_header_get_folder (header);
5912
5913                 /* Transfer the messages */
5914                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
5915                                                             headers,
5916                                                             TNY_FOLDER (dst_folder));
5917
5918                 /* Frees */
5919                 g_object_unref (header);
5920                 g_object_unref (iter);
5921                 g_object_unref (src_folder);
5922         }
5923 }
5924
5925 void
5926 modest_ui_actions_on_move_to (GtkAction *action,
5927                               ModestWindow *win)
5928 {
5929         modest_ui_actions_on_edit_mode_move_to (win);
5930 }
5931
5932 gboolean
5933 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5934 {
5935         GtkWidget *dialog = NULL;
5936         MoveToInfo *helper = NULL;
5937         TnyList *list_to_move;
5938
5939         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5940
5941 #ifndef MODEST_TOOLKIT_HILDON2
5942         /* Get the main window if exists */
5943         ModestMainWindow *main_window;
5944         if (MODEST_IS_MAIN_WINDOW (win))
5945                 main_window = MODEST_MAIN_WINDOW (win);
5946         else
5947                 main_window =
5948                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5949                                                                                FALSE)); /* don't create */
5950 #endif
5951
5952         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5953
5954         if (!list_to_move)
5955                 return FALSE;
5956
5957         if (tny_list_get_length (list_to_move) < 1) {
5958                 g_object_unref (list_to_move);
5959                 return FALSE;
5960         }
5961
5962         /* Create and run the dialog */
5963         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
5964         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5965                                      GTK_WINDOW (dialog),
5966                                      (GtkWindow *) win);
5967
5968         /* Create helper */
5969         helper = g_slice_new0 (MoveToInfo);
5970         helper->list = list_to_move;
5971         helper->win = win;
5972
5973         /* Listen to response signal */
5974         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5975
5976         /* Show the dialog */
5977         gtk_widget_show (dialog);
5978
5979         return TRUE;
5980 }
5981
5982 /*
5983  * Calls #HeadersFunc for each header already selected in the main
5984  * window or the message currently being shown in the msg view window
5985  */
5986 static void
5987 do_headers_action (ModestWindow *win,
5988                    HeadersFunc func,
5989                    gpointer user_data)
5990 {
5991         TnyList *headers_list = NULL;
5992         TnyIterator *iter = NULL;
5993         TnyHeader *header = NULL;
5994         TnyFolder *folder = NULL;
5995
5996         /* Get headers */
5997         headers_list = get_selected_headers (win);
5998         if (!headers_list)
5999                 return;
6000
6001         /* Get the folder */
6002         iter = tny_list_create_iterator (headers_list);
6003         header = TNY_HEADER (tny_iterator_get_current (iter));
6004         if (header) {
6005                 folder = tny_header_get_folder (header);
6006                 g_object_unref (header);
6007         }
6008
6009         /* Call the function for each header */
6010         while (!tny_iterator_is_done (iter)) {
6011                 header = TNY_HEADER (tny_iterator_get_current (iter));
6012                 func (header, win, user_data);
6013                 g_object_unref (header);
6014                 tny_iterator_next (iter);
6015         }
6016
6017         /* Trick: do a poke status in order to speed up the signaling
6018            of observers */
6019         if (folder) {
6020                 tny_folder_poke_status (folder);
6021                 g_object_unref (folder);
6022         }
6023
6024         /* Frees */
6025         g_object_unref (iter);
6026         g_object_unref (headers_list);
6027 }
6028
6029 void
6030 modest_ui_actions_view_attachment (GtkAction *action,
6031                                    ModestWindow *window)
6032 {
6033         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6034                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6035         } else {
6036                 /* not supported window for this action */
6037                 g_return_if_reached ();
6038         }
6039 }
6040
6041 void
6042 modest_ui_actions_save_attachments (GtkAction *action,
6043                                     ModestWindow *window)
6044 {
6045         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6046
6047                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6048                         return;
6049
6050                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6051         } else {
6052                 /* not supported window for this action */
6053                 g_return_if_reached ();
6054         }
6055 }
6056
6057 void
6058 modest_ui_actions_remove_attachments (GtkAction *action,
6059                                       ModestWindow *window)
6060 {
6061         if (MODEST_IS_MAIN_WINDOW (window)) {
6062                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6063         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6064                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6065         } else {
6066                 /* not supported window for this action */
6067                 g_return_if_reached ();
6068         }
6069 }
6070
6071 void
6072 modest_ui_actions_on_settings (GtkAction *action,
6073                                ModestWindow *win)
6074 {
6075         GtkWidget *dialog;
6076
6077         dialog = modest_platform_get_global_settings_dialog ();
6078         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6079         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6080         gtk_widget_show_all (dialog);
6081
6082         gtk_dialog_run (GTK_DIALOG (dialog));
6083
6084         gtk_widget_destroy (dialog);
6085 }
6086
6087 void
6088 modest_ui_actions_on_help (GtkAction *action,
6089                            GtkWindow *win)
6090 {
6091         /* Help app is not available at all in fremantle */
6092 #ifndef MODEST_TOOLKIT_HILDON2
6093         const gchar *help_id;
6094
6095         g_return_if_fail (win && GTK_IS_WINDOW(win));
6096
6097         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6098
6099         if (help_id)
6100                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6101 #endif
6102 }
6103
6104 void
6105 modest_ui_actions_on_csm_help (GtkAction *action,
6106                                GtkWindow *win)
6107 {
6108         /* Help app is not available at all in fremantle */
6109 #ifndef MODEST_TOOLKIT_HILDON2
6110
6111         const gchar* help_id = NULL;
6112         GtkWidget *folder_view;
6113         TnyFolderStore *folder_store;
6114
6115         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6116
6117         /* Get selected folder */
6118         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6119                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6120         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6121
6122         /* Switch help_id */
6123         if (folder_store && TNY_IS_FOLDER (folder_store))
6124                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6125
6126         if (folder_store)
6127                 g_object_unref (folder_store);
6128
6129         if (help_id)
6130                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6131         else
6132                 modest_ui_actions_on_help (action, win);
6133 #endif
6134 }
6135
6136 static void
6137 retrieve_contents_cb (ModestMailOperation *mail_op,
6138                       TnyHeader *header,
6139                       gboolean canceled,
6140                       TnyMsg *msg,
6141                       GError *err,
6142                       gpointer user_data)
6143 {
6144         /* We only need this callback to show an error in case of
6145            memory low condition */
6146         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6147                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6148         }
6149 }
6150
6151 static void
6152 retrieve_msg_contents_performer (gboolean canceled,
6153                                  GError *err,
6154                                  GtkWindow *parent_window,
6155                                  TnyAccount *account,
6156                                  gpointer user_data)
6157 {
6158         ModestMailOperation *mail_op;
6159         TnyList *headers = TNY_LIST (user_data);
6160
6161         if (err || canceled) {
6162                 check_memory_full_error ((GtkWidget *) parent_window, err);
6163                 goto out;
6164         }
6165
6166         /* Create mail operation */
6167         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6168                                                                  modest_ui_actions_disk_operations_error_handler,
6169                                                                  NULL, NULL);
6170         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6171         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6172
6173         /* Frees */
6174         g_object_unref (mail_op);
6175  out:
6176         g_object_unref (headers);
6177         g_object_unref (account);
6178 }
6179
6180 void
6181 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6182                                             ModestWindow *window)
6183 {
6184         TnyList *headers = NULL;
6185         TnyAccount *account = NULL;
6186         TnyIterator *iter = NULL;
6187         TnyHeader *header = NULL;
6188         TnyFolder *folder = NULL;
6189
6190         /* Get headers */
6191         headers = get_selected_headers (window);
6192         if (!headers)
6193                 return;
6194
6195         /* Pick the account */
6196         iter = tny_list_create_iterator (headers);
6197         header = TNY_HEADER (tny_iterator_get_current (iter));
6198         folder = tny_header_get_folder (header);
6199         account = tny_folder_get_account (folder);
6200         g_object_unref (folder);
6201         g_object_unref (header);
6202         g_object_unref (iter);
6203
6204         /* Connect and perform the message retrieval */
6205         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6206                                              g_object_ref (account),
6207                                              retrieve_msg_contents_performer,
6208                                              g_object_ref (headers));
6209
6210         /* Frees */
6211         g_object_unref (account);
6212         g_object_unref (headers);
6213 }
6214
6215 void
6216 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6217 {
6218         g_return_if_fail (MODEST_IS_WINDOW (window));
6219
6220         /* Update dimmed */
6221         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6222 }
6223
6224 void
6225 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6226 {
6227         g_return_if_fail (MODEST_IS_WINDOW (window));
6228
6229         /* Update dimmed */
6230         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6231 }
6232
6233 void
6234 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6235                                           ModestWindow *window)
6236 {
6237         g_return_if_fail (MODEST_IS_WINDOW (window));
6238
6239         /* Update dimmed */
6240         modest_ui_actions_check_menu_dimming_rules (window);
6241 }
6242
6243 void
6244 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6245                                           ModestWindow *window)
6246 {
6247         g_return_if_fail (MODEST_IS_WINDOW (window));
6248
6249         /* Update dimmed */
6250         modest_ui_actions_check_menu_dimming_rules (window);
6251 }
6252
6253 void
6254 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6255                                           ModestWindow *window)
6256 {
6257         g_return_if_fail (MODEST_IS_WINDOW (window));
6258
6259         /* Update dimmed */
6260         modest_ui_actions_check_menu_dimming_rules (window);
6261 }
6262
6263 void
6264 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6265                                             ModestWindow *window)
6266 {
6267         g_return_if_fail (MODEST_IS_WINDOW (window));
6268
6269         /* Update dimmed */
6270         modest_ui_actions_check_menu_dimming_rules (window);
6271 }
6272
6273 void
6274 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6275                                           ModestWindow *window)
6276 {
6277         g_return_if_fail (MODEST_IS_WINDOW (window));
6278
6279         /* Update dimmed */
6280         modest_ui_actions_check_menu_dimming_rules (window);
6281 }
6282
6283 void
6284 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6285                                           ModestWindow *window)
6286 {
6287         g_return_if_fail (MODEST_IS_WINDOW (window));
6288
6289         /* Update dimmed */
6290         modest_ui_actions_check_menu_dimming_rules (window);
6291 }
6292
6293 void
6294 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6295                                                  ModestWindow *window)
6296 {
6297         g_return_if_fail (MODEST_IS_WINDOW (window));
6298
6299         /* Update dimmed */
6300         modest_ui_actions_check_menu_dimming_rules (window);
6301 }
6302
6303 void
6304 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6305                                                      ModestWindow *window)
6306 {
6307         g_return_if_fail (MODEST_IS_WINDOW (window));
6308
6309         /* Update dimmed */
6310         modest_ui_actions_check_menu_dimming_rules (window);
6311 }
6312
6313 void
6314 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6315                                                      ModestWindow *window)
6316 {
6317         g_return_if_fail (MODEST_IS_WINDOW (window));
6318
6319         /* Update dimmed */
6320         modest_ui_actions_check_menu_dimming_rules (window);
6321 }
6322
6323 void
6324 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6325 {
6326         g_return_if_fail (MODEST_IS_WINDOW (window));
6327
6328         /* we check for low-mem; in that case, show a warning, and don't allow
6329          * searching
6330          */
6331         if (modest_platform_check_memory_low (window, TRUE))
6332                 return;
6333
6334         modest_platform_show_search_messages (GTK_WINDOW (window));
6335 }
6336
6337 void
6338 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6339 {
6340         g_return_if_fail (MODEST_IS_WINDOW (win));
6341
6342
6343         /* we check for low-mem; in that case, show a warning, and don't allow
6344          * for the addressbook
6345          */
6346         if (modest_platform_check_memory_low (win, TRUE))
6347                 return;
6348
6349
6350         modest_platform_show_addressbook (GTK_WINDOW (win));
6351 }
6352
6353
6354 void
6355 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6356                                           ModestWindow *window)
6357 {
6358         gboolean active;
6359         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6360
6361         if (GTK_IS_TOGGLE_ACTION (action))
6362                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6363         else
6364                 active = TRUE;
6365
6366         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6367                                                     active);
6368 }
6369
6370 static void
6371 on_send_receive_finished (ModestMailOperation  *mail_op,
6372                            gpointer user_data)
6373 {
6374         GtkWidget *header_view, *folder_view;
6375         TnyFolderStore *folder_store;
6376         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6377
6378         /* Set send/receive operation finished */
6379         modest_main_window_notify_send_receive_completed (main_win);
6380
6381         /* Don't refresh the current folder if there were any errors */
6382         if (modest_mail_operation_get_status (mail_op) !=
6383             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6384                 return;
6385
6386         /* Refresh the current folder if we're viewing a window. We do
6387            this because the user won't be able to see the new mails in
6388            the selected folder after a Send&Receive because it only
6389            performs a poke_status, i.e, only the number of read/unread
6390            messages is updated, but the new headers are not
6391            downloaded */
6392         folder_view = modest_main_window_get_child_widget (main_win,
6393                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6394         if (!folder_view)
6395                 return;
6396
6397         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6398
6399         /* Do not need to refresh INBOX again because the
6400            update_account does it always automatically */
6401         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6402             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6403                 ModestMailOperation *refresh_op;
6404
6405                 header_view = modest_main_window_get_child_widget (main_win,
6406                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6407
6408                 /* We do not need to set the contents style
6409                    because it hasn't changed. We also do not
6410                    need to save the widget status. Just force
6411                    a refresh */
6412                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6413                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6414                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6415                                                       folder_refreshed_cb, main_win);
6416                 g_object_unref (refresh_op);
6417         }
6418
6419         if (folder_store)
6420                 g_object_unref (folder_store);
6421 }
6422
6423
6424 void
6425 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6426                                                 TnyHeader *header,
6427                                                 TnyMsg *msg,
6428                                                 GError *err,
6429                                                 gpointer user_data)
6430 {
6431         const gchar* server_name = NULL;
6432         TnyTransportAccount *transport;
6433         gchar *message = NULL;
6434         ModestProtocol *protocol;
6435
6436         /* Don't show anything if the user cancelled something or the
6437          * send receive request is not interactive. Authentication
6438          * errors are managed by the account store so no need to show
6439          * a dialog here again */
6440         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6441             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6442             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6443                 return;
6444
6445
6446         /* Get the server name. Note that we could be using a
6447            connection specific transport account */
6448         transport = (TnyTransportAccount *)
6449                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6450         if (transport) {
6451                 ModestTnyAccountStore *acc_store;
6452                 const gchar *acc_name;
6453                 TnyTransportAccount *conn_specific;
6454
6455                 acc_store = modest_runtime_get_account_store();
6456                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6457                 conn_specific = (TnyTransportAccount *)
6458                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6459                 if (conn_specific) {
6460                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6461                         g_object_unref (conn_specific);
6462                 } else {
6463                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6464                 }
6465                 g_object_unref (transport);
6466         }
6467
6468         /* Get protocol */
6469         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6470                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6471                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6472         if (!protocol) {
6473                 g_warning ("%s: Account with no proto", __FUNCTION__);
6474                 return;
6475         }
6476
6477         /* Show the appropriate message text for the GError: */
6478         switch (err->code) {
6479         case TNY_SERVICE_ERROR_CONNECT:
6480                 message = modest_protocol_get_translation (protocol,
6481                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6482                                                            server_name);
6483                 break;
6484         case TNY_SERVICE_ERROR_SEND:
6485                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6486                 break;
6487         case TNY_SERVICE_ERROR_UNAVAILABLE:
6488                 message = modest_protocol_get_translation (protocol,
6489                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6490                                                            server_name);
6491                 break;
6492         default:
6493                 g_warning ("%s: unexpected ERROR %d",
6494                            __FUNCTION__, err->code);
6495                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6496                 break;
6497         }
6498
6499         modest_platform_run_information_dialog (NULL, message, FALSE);
6500         g_free (message);
6501 }
6502
6503 void
6504 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6505                                                 gchar *msg_id,
6506                                                 guint status,
6507                                                 gpointer user_data)
6508 {
6509         ModestWindow *top_window = NULL;
6510         ModestWindowMgr *mgr = NULL;
6511         GtkWidget *header_view = NULL;
6512         TnyFolder *selected_folder = NULL;
6513         TnyFolderType folder_type;
6514
6515         mgr = modest_runtime_get_window_mgr ();
6516         top_window = modest_window_mgr_get_current_top (mgr);
6517
6518         if (!top_window)
6519                 return;
6520
6521 #ifndef MODEST_TOOLKIT_HILDON2
6522         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6523                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6524                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6525         }
6526 #else
6527         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6528                 header_view = (GtkWidget *)
6529                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6530         }
6531 #endif
6532
6533         /* Get selected folder */
6534         if (header_view)
6535                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6536         if (!selected_folder)
6537                 return;
6538
6539         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6540 #if GTK_CHECK_VERSION(2, 8, 0)
6541         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6542         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6543                 GtkTreeViewColumn *tree_column;
6544
6545                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6546                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6547                 if (tree_column)
6548                         gtk_tree_view_column_queue_resize (tree_column);
6549                 }
6550 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6551         gtk_widget_queue_draw (header_view);
6552 #endif
6553
6554 #ifndef MODEST_TOOLKIT_HILDON2
6555         /* Rerun dimming rules, because the message could become deletable for example */
6556         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6557                                                  MODEST_DIMMING_RULES_TOOLBAR);
6558         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6559                                                  MODEST_DIMMING_RULES_MENU);
6560 #endif
6561
6562         /* Free */
6563         g_object_unref (selected_folder);
6564 }
6565
6566 void
6567 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6568                                                TnyAccount *account)
6569 {
6570         ModestProtocolType protocol_type;
6571         ModestProtocol *protocol;
6572         gchar *error_note = NULL;
6573
6574         protocol_type = modest_tny_account_get_protocol_type (account);
6575         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6576                                                                   protocol_type);
6577
6578         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6579         if (error_note == NULL) {
6580                 g_warning ("%s: This should not be reached", __FUNCTION__);
6581         } else {
6582                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6583                 g_free (error_note);
6584         }
6585 }
6586
6587 gchar *
6588 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6589 {
6590         gchar *msg = NULL;
6591         gchar *subject;
6592         TnyFolderStore *folder = NULL;
6593         TnyAccount *account = NULL;
6594         ModestProtocolType proto;
6595         ModestProtocol *protocol;
6596         TnyHeader *header = NULL;
6597
6598         if (MODEST_IS_MAIN_WINDOW (win)) {
6599                 GtkWidget *header_view;
6600                 TnyList* headers = NULL;
6601                 TnyIterator *iter;
6602                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6603                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6604                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6605                 if (!headers || tny_list_get_length (headers) == 0) {
6606                         if (headers)
6607                                 g_object_unref (headers);
6608                         return NULL;
6609                 }
6610                 iter = tny_list_create_iterator (headers);
6611                 header = TNY_HEADER (tny_iterator_get_current (iter));
6612                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6613                 g_object_unref (iter);
6614                 g_object_unref (headers);
6615 #ifdef MODEST_TOOLKIT_HILDON2
6616         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6617                 GtkWidget *header_view;
6618                 TnyList* headers = NULL;
6619                 TnyIterator *iter;
6620                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6621                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6622                 if (!headers || tny_list_get_length (headers) == 0) {
6623                         if (headers)
6624                                 g_object_unref (headers);
6625                         return NULL;
6626                 }
6627                 iter = tny_list_create_iterator (headers);
6628                 header = TNY_HEADER (tny_iterator_get_current (iter));
6629                 if (header) {
6630                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6631                 } else {
6632                         g_warning ("List should contain headers");
6633                 }
6634                 g_object_unref (iter);
6635                 g_object_unref (headers);
6636 #endif
6637         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6638                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6639                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6640         }
6641
6642         if (!header || !folder)
6643                 goto frees;
6644
6645         /* Get the account type */
6646         account = tny_folder_get_account (TNY_FOLDER (folder));
6647         proto = modest_tny_account_get_protocol_type (account);
6648         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6649                                                                   proto);
6650
6651         subject = tny_header_dup_subject (header);
6652         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6653         if (subject)
6654                 g_free (subject);
6655         if (msg == NULL) {
6656                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6657         }
6658
6659  frees:
6660         /* Frees */
6661         if (account)
6662                 g_object_unref (account);
6663         if (folder)
6664                 g_object_unref (folder);
6665         if (header)
6666                 g_object_unref (header);
6667
6668         return msg;
6669 }
6670
6671 gboolean
6672 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6673                                      const gchar *account_name,
6674                                      const gchar *account_title)
6675 {
6676         ModestAccountMgr *account_mgr;
6677         gchar *txt = NULL;
6678         gint response;
6679         ModestProtocol *protocol;
6680         gboolean removed = FALSE;
6681
6682         g_return_val_if_fail (account_name, FALSE);
6683         g_return_val_if_fail (account_title, FALSE);
6684
6685         account_mgr = modest_runtime_get_account_mgr();
6686
6687         /* The warning text depends on the account type: */
6688         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6689                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6690                                                                                                          account_name));
6691         txt = modest_protocol_get_translation (protocol,
6692                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6693                                                account_title);
6694         if (txt == NULL)
6695                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6696
6697         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6698         g_free (txt);
6699         txt = NULL;
6700
6701         if (response == GTK_RESPONSE_OK) {
6702                 /* Remove account. If it succeeds then it also removes
6703                    the account from the ModestAccountView: */
6704                 gboolean is_default = FALSE;
6705                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6706                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6707                         is_default = TRUE;
6708                 g_free (default_account_name);
6709
6710                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6711                 if (!removed)
6712                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6713         }
6714         return removed;
6715 }
6716
6717 void 
6718 modest_ui_actions_on_fetch_images (GtkAction *action,
6719                                    ModestWindow *window)
6720 {
6721         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6722
6723         modest_msg_view_window_fetch_images (MODEST_MSG_VIEW_WINDOW (window));
6724
6725 }
6726
6727 void
6728 modest_ui_actions_on_reload_message (const gchar *msg_id)
6729 {
6730         ModestWindow *window = NULL;
6731
6732         g_return_if_fail (msg_id && msg_id[0] != '\0');
6733         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6734                                                             msg_id,
6735                                                             &window))
6736                 return;
6737
6738
6739         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6740                 return;
6741
6742         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6743 }