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