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