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