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