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