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