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