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