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