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