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