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