Now GetUnreadMessages dbus method tells also the number of unread messages
[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 result = TRUE, add_to_contacts;
3387         MsgData *data;
3388         ModestAccountMgr *account_mgr;
3389         gchar *account_name;
3390         gchar *recipients;
3391
3392         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3393
3394         /* Check whether to automatically add new contacts to addressbook or not */
3395         add_to_contacts = modest_conf_get_bool (modest_runtime_get_conf (),
3396                                                 MODEST_CONF_AUTO_ADD_TO_CONTACTS, NULL);
3397         if (!modest_msg_edit_window_check_names (edit_window, add_to_contacts))
3398                 return TRUE;
3399
3400         data = modest_msg_edit_window_get_msg_data (edit_window);
3401
3402         recipients = g_strconcat (data->to?data->to:"", 
3403                                   data->cc?data->cc:"",
3404                                   data->bcc?data->bcc:"",
3405                                   NULL);
3406         if (recipients == NULL || recipients[0] == '\0') {
3407                 /* Empty subject -> no send */
3408                 g_free (recipients);
3409                 modest_msg_edit_window_free_msg_data (edit_window, data);
3410                 return FALSE;
3411         }
3412         g_free (recipients);
3413
3414         /* Check size */
3415         if (!enough_space_for_message (edit_window, data)) {
3416                 modest_msg_edit_window_free_msg_data (edit_window, data);
3417                 return FALSE;
3418         }
3419
3420         account_mgr = modest_runtime_get_account_mgr();
3421         account_name = g_strdup (data->account_name);
3422         if (!account_name)
3423                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3424
3425         if (!account_name)
3426                 account_name = modest_account_mgr_get_default_account (account_mgr);
3427
3428         if (!account_name) {
3429                 modest_msg_edit_window_free_msg_data (edit_window, data);
3430                 /* Run account setup wizard */
3431                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3432                         return TRUE;
3433                 }
3434         }
3435
3436         /* Get the currently-active transport account for this modest account: */
3437         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3438                 transport_account =
3439                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3440                                               (modest_runtime_get_account_store (),
3441                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3442         }
3443
3444         if (!transport_account) {
3445                 modest_msg_edit_window_free_msg_data (edit_window, data);
3446                 /* Run account setup wizard */
3447                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3448                         return TRUE;
3449         }
3450
3451         result = modest_ui_actions_send_msg_with_transport (transport_account,
3452                                                             data->draft_msg,
3453                                                             data->from,
3454                                                             data->to,
3455                                                             data->cc,
3456                                                             data->bcc,
3457                                                             data->subject,
3458                                                             data->plain_body,
3459                                                             data->html_body,
3460                                                             data->attachments,
3461                                                             data->images,
3462                                                             data->references,
3463                                                             data->in_reply_to,
3464                                                             data->priority_flags,
3465                                                             data->custom_header_pairs);
3466
3467
3468         /* Free data: */
3469         g_free (account_name);
3470         g_object_unref (G_OBJECT (transport_account));
3471
3472         modest_msg_edit_window_free_msg_data (edit_window, data);
3473
3474         if (result) {
3475                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3476
3477                 /* Save settings and close the window: */
3478                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3479         }
3480
3481         return result;
3482 }
3483
3484 /* For instance, when clicking the Send toolbar button when editing a message: */
3485 gboolean
3486 modest_ui_actions_on_send_custom_msg (const gchar *account_name, 
3487                                       const gchar *from, const gchar *to, const gchar *cc, const gchar *bcc,
3488                                       const gchar *subject,
3489                                       const gchar *plain_body, const gchar *html_body,
3490                                       const GList *attachments_list, const GList *images_list,
3491                                       const gchar *references, const gchar *in_reply_to,
3492                                       TnyHeaderFlags priority_flags, TnyList *header_pairs)
3493 {
3494         TnyTransportAccount *transport_account = NULL;
3495         gboolean result = FALSE;
3496
3497         g_return_val_if_fail (account_name, FALSE);
3498
3499         transport_account =
3500           TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3501                                 (modest_runtime_get_account_store (),
3502                                  account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3503
3504         g_return_val_if_fail (transport_account, FALSE);
3505
3506         result = modest_ui_actions_send_msg_with_transport (transport_account,
3507                                                             NULL /*draft msg*/,
3508                                                             from, to, cc, bcc,
3509                                                             subject,
3510                                                             plain_body, html_body,
3511                                                             attachments_list, images_list,
3512                                                             references, in_reply_to,
3513                                                             priority_flags, header_pairs);
3514
3515         /* Free data: */
3516         g_object_unref (G_OBJECT (transport_account));
3517
3518         return result;
3519 }
3520
3521 gboolean
3522 modest_ui_actions_send_msg_with_transport (TnyTransportAccount *transport_account, 
3523                                            TnyMsg *draft_msg,
3524                                            const gchar *from, const gchar *to, const gchar *cc, const gchar *bcc,
3525                                            const gchar *subject,
3526                                            const gchar *plain_body, const gchar *html_body,
3527                                            const GList *attachments_list, const GList *images_list,
3528                                            const gchar *references, const gchar *in_reply_to,
3529                                            TnyHeaderFlags priority_flags, TnyList *header_pairs)
3530 {
3531         gboolean had_error = FALSE;
3532         ModestMailOperation *mail_operation;
3533
3534         g_return_val_if_fail (transport_account, FALSE);
3535
3536         /* Create the mail operation */
3537         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3538         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3539
3540         modest_mail_operation_send_new_mail (mail_operation,
3541                                              transport_account,
3542                                              draft_msg,
3543                                              from,
3544                                              to,
3545                                              cc,
3546                                              bcc,
3547                                              subject,
3548                                              plain_body,
3549                                              html_body,
3550                                              attachments_list,
3551                                              images_list,
3552                                              references,
3553                                              in_reply_to,
3554                                              priority_flags,
3555                                              header_pairs);
3556
3557         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3558                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3559
3560         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3561                 const GError *error = modest_mail_operation_get_error (mail_operation);
3562                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3563                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3564                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3565                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3566                         had_error = TRUE;
3567                 }
3568         }
3569
3570         /* Free data: */
3571         g_object_unref (G_OBJECT (mail_operation));
3572
3573         return !had_error;
3574 }
3575
3576 gboolean
3577 modest_ui_actions_on_send_msg (ModestWindow *window,
3578                                TnyMsg *msg)
3579 {
3580         TnyTransportAccount *transport_account = NULL;
3581         gboolean had_error = FALSE;
3582         ModestAccountMgr *account_mgr;
3583         gchar *account_name;
3584         ModestMailOperation *mail_operation;
3585
3586         account_mgr = modest_runtime_get_account_mgr();
3587         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(window)));
3588
3589         if (!account_name)
3590                 account_name = modest_account_mgr_get_default_account (account_mgr);
3591
3592         /* Get the currently-active transport account for this modest account: */
3593         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3594                 transport_account =
3595                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3596                                               (modest_runtime_get_account_store (),
3597                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3598         }
3599
3600         /* Create the mail operation */
3601         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3602         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3603
3604         modest_mail_operation_send_mail (mail_operation,
3605                                          transport_account,
3606                                          msg);
3607
3608         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3609                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3610
3611         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3612                 const GError *error = modest_mail_operation_get_error (mail_operation);
3613                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3614                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3615                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3616                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3617                         had_error = TRUE;
3618                 }
3619         }
3620
3621         /* Free data: */
3622         g_free (account_name);
3623         g_object_unref (G_OBJECT (transport_account));
3624         g_object_unref (G_OBJECT (mail_operation));
3625
3626         return !had_error;
3627 }
3628
3629 void
3630 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3631                                   ModestMsgEditWindow *window)
3632 {
3633         ModestMsgEditFormatState *format_state = NULL;
3634
3635         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3636         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3637
3638         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3639                 return;
3640
3641         format_state = modest_msg_edit_window_get_format_state (window);
3642         g_return_if_fail (format_state != NULL);
3643
3644         format_state->bold = gtk_toggle_action_get_active (action);
3645         modest_msg_edit_window_set_format_state (window, format_state);
3646         g_free (format_state);
3647
3648 }
3649
3650 void
3651 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3652                                      ModestMsgEditWindow *window)
3653 {
3654         ModestMsgEditFormatState *format_state = NULL;
3655
3656         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3657         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3658
3659         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3660                 return;
3661
3662         format_state = modest_msg_edit_window_get_format_state (window);
3663         g_return_if_fail (format_state != NULL);
3664
3665         format_state->italics = gtk_toggle_action_get_active (action);
3666         modest_msg_edit_window_set_format_state (window, format_state);
3667         g_free (format_state);
3668
3669 }
3670
3671 void
3672 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3673                                      ModestMsgEditWindow *window)
3674 {
3675         ModestMsgEditFormatState *format_state = NULL;
3676
3677         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3678         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3679
3680         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3681                 return;
3682
3683         format_state = modest_msg_edit_window_get_format_state (window);
3684         g_return_if_fail (format_state != NULL);
3685
3686         format_state->bullet = gtk_toggle_action_get_active (action);
3687         modest_msg_edit_window_set_format_state (window, format_state);
3688         g_free (format_state);
3689
3690 }
3691
3692 void
3693 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3694                                      GtkRadioAction *selected,
3695                                      ModestMsgEditWindow *window)
3696 {
3697         ModestMsgEditFormatState *format_state = NULL;
3698         GtkJustification value;
3699
3700         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3701
3702         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3703                 return;
3704
3705         value = gtk_radio_action_get_current_value (selected);
3706
3707         format_state = modest_msg_edit_window_get_format_state (window);
3708         g_return_if_fail (format_state != NULL);
3709
3710         format_state->justification = value;
3711         modest_msg_edit_window_set_format_state (window, format_state);
3712         g_free (format_state);
3713 }
3714
3715 void
3716 modest_ui_actions_on_select_editor_color (GtkAction *action,
3717                                           ModestMsgEditWindow *window)
3718 {
3719         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3720         g_return_if_fail (GTK_IS_ACTION (action));
3721
3722         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3723                 return;
3724
3725         modest_msg_edit_window_select_color (window);
3726 }
3727
3728 void
3729 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3730                                                      ModestMsgEditWindow *window)
3731 {
3732         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3733         g_return_if_fail (GTK_IS_ACTION (action));
3734
3735         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3736                 return;
3737
3738         modest_msg_edit_window_select_background_color (window);
3739 }
3740
3741 void
3742 modest_ui_actions_on_insert_image (GObject *object,
3743                                    ModestMsgEditWindow *window)
3744 {
3745         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3746
3747
3748         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3749                 return;
3750
3751         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3752                 return;
3753
3754         modest_msg_edit_window_insert_image (window);
3755 }
3756
3757 void
3758 modest_ui_actions_on_attach_file (GtkAction *action,
3759                                   ModestMsgEditWindow *window)
3760 {
3761         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3762         g_return_if_fail (GTK_IS_ACTION (action));
3763
3764         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3765                 return;
3766
3767         modest_msg_edit_window_offer_attach_file (window);
3768 }
3769
3770 void
3771 modest_ui_actions_on_remove_attachments (GtkAction *action,
3772                                          ModestMsgEditWindow *window)
3773 {
3774         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3775
3776         modest_msg_edit_window_remove_attachments (window, NULL);
3777 }
3778
3779 static void
3780 do_create_folder_cb (ModestMailOperation *mail_op,
3781                      TnyFolderStore *parent_folder,
3782                      TnyFolder *new_folder,
3783                      gpointer user_data)
3784 {
3785         gchar *suggested_name = (gchar *) user_data;
3786         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3787         const GError *error;
3788
3789         error = modest_mail_operation_get_error (mail_op);
3790         if (error) {
3791                 gboolean disk_full = FALSE;
3792                 TnyAccount *account;
3793                 /* Show an error. If there was some problem writing to
3794                    disk, show it, otherwise show the generic folder
3795                    create error. We do it here and not in an error
3796                    handler because the call to do_create_folder will
3797                    stop the main loop in a gtk_dialog_run and then,
3798                    the message won't be shown until that dialog is
3799                    closed */
3800                 account = modest_mail_operation_get_account (mail_op);
3801                 if (account) {
3802                         disk_full =
3803                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3804                                                                                 (GtkWidget *) source_win,
3805                                                                                 (GError *) error,
3806                                                                                 account,
3807                                                                                 _("mail_in_ui_folder_create_error_memory"));
3808                         g_object_unref (account);
3809                 }
3810                 if (!disk_full) {
3811                         /* Show an error and try again if there is no
3812                            full memory condition */
3813                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3814                                                             _("mail_in_ui_folder_create_error"));
3815                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3816                 }
3817
3818         } else {
3819                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3820                  * FIXME: any other? */
3821                 GtkWidget *folder_view;
3822
3823                 if (MODEST_IS_MAIN_WINDOW(source_win))
3824                         folder_view =
3825                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3826                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3827                 else
3828                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3829                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3830
3831                 /* Select the newly created folder. It could happen
3832                    that the widget is no longer there (i.e. the window
3833                    has been destroyed, so we need to check this */
3834                 if (folder_view)
3835                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3836                                                           new_folder, FALSE);
3837                 g_object_unref (new_folder);
3838         }
3839         /* Free. Note that the first time it'll be NULL so noop */
3840         g_free (suggested_name);
3841         g_object_unref (source_win);
3842 }
3843
3844 typedef struct {
3845         gchar *folder_name;
3846         TnyFolderStore *parent;
3847 } CreateFolderConnect;
3848
3849 static void
3850 do_create_folder_performer (gboolean canceled,
3851                          GError *err,
3852                          GtkWindow *parent_window,
3853                          TnyAccount *account,
3854                          gpointer user_data)
3855 {
3856         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3857         ModestMailOperation *mail_op;
3858
3859         if (canceled || err) {
3860                 /* In disk full conditions we could get this error here */
3861                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3862                                                                 (GtkWidget *) parent_window, err,
3863                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3864
3865                 /* This happens if we have selected the outbox folder
3866                    as the parent */
3867                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3868                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3869                         /* Show an error and retry */
3870                         modest_platform_information_banner ((GtkWidget *) parent_window,
3871                                                             NULL,
3872                                                             _("mail_in_ui_folder_create_error"));
3873
3874                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3875                 }
3876
3877                 goto frees;
3878         }
3879
3880         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3881         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3882                                          mail_op);
3883         modest_mail_operation_create_folder (mail_op,
3884                                              helper->parent,
3885                                              (const gchar *) helper->folder_name,
3886                                              do_create_folder_cb,
3887                                              g_strdup (helper->folder_name));
3888         g_object_unref (mail_op);
3889
3890  frees:
3891         if (helper->parent)
3892                 g_object_unref (helper->parent);
3893         if (helper->folder_name)
3894                 g_free (helper->folder_name);
3895         g_slice_free (CreateFolderConnect, helper);
3896 }
3897
3898
3899 static void
3900 do_create_folder (GtkWindow *parent_window,
3901                   TnyFolderStore *suggested_parent,
3902                   const gchar *suggested_name)
3903 {
3904         gint result;
3905         gchar *folder_name = NULL;
3906         TnyFolderStore *parent_folder = NULL;
3907
3908         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3909                                                         suggested_parent,
3910                                                         (gchar *) suggested_name,
3911                                                         &folder_name,
3912                                                         &parent_folder);
3913
3914         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3915                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3916                 helper->folder_name = g_strdup (folder_name);
3917                 helper->parent = g_object_ref (parent_folder);
3918
3919                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3920                                                                TRUE,
3921                                                                parent_folder,
3922                                                                do_create_folder_performer,
3923                                                                helper);
3924         }
3925
3926         if (folder_name)
3927                 g_free (folder_name);
3928         if (parent_folder)
3929                 g_object_unref (parent_folder);
3930 }
3931
3932 static void
3933 modest_ui_actions_create_folder(GtkWidget *parent_window,
3934                                 GtkWidget *folder_view,
3935                                 TnyFolderStore *parent_folder)
3936 {
3937         if (!parent_folder) {
3938 #ifdef MODEST_TOOLKIT_HILDON2
3939                 ModestTnyAccountStore *acc_store;
3940
3941                 acc_store = modest_runtime_get_account_store ();
3942
3943                 parent_folder = (TnyFolderStore *)
3944                         modest_tny_account_store_get_local_folders_account (acc_store);
3945 #else
3946                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3947 #endif
3948         }
3949
3950         if (parent_folder) {
3951                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3952                 g_object_unref (parent_folder);
3953         }
3954 }
3955
3956 void
3957 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3958 {
3959
3960         g_return_if_fail (MODEST_IS_WINDOW(window));
3961
3962         if (MODEST_IS_MAIN_WINDOW (window)) {
3963                 GtkWidget *folder_view;
3964
3965                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3966                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3967                 if (!folder_view)
3968                         return;
3969
3970                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3971 #ifdef MODEST_TOOLKIT_HILDON2
3972         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3973                 GtkWidget *folder_view;
3974
3975                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3976                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3977 #endif
3978         } else {
3979                 g_assert_not_reached ();
3980         }
3981 }
3982
3983 static void
3984 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3985                                                gpointer user_data)
3986 {
3987         const GError *error = NULL;
3988         gchar *message = NULL;
3989         gboolean mem_full;
3990         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3991
3992         /* Get error message */
3993         error = modest_mail_operation_get_error (mail_op);
3994         if (!error)
3995                 g_return_if_reached ();
3996
3997         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3998                                                                 (GError *) error, account);
3999         if (mem_full) {
4000                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
4001         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
4002                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
4003                 message = _CS("ckdg_ib_folder_already_exists");
4004         } else if (error->domain == TNY_ERROR_DOMAIN &&
4005                    error->code == TNY_SERVICE_ERROR_STATE) {
4006                 /* This means that the folder is already in use (a
4007                    message is opened for example */
4008                 message = _("emev_ni_internal_error");
4009         } else {
4010                 message = _CS("ckdg_ib_unable_to_rename");
4011         }
4012
4013         /* We don't set a parent for the dialog because the dialog
4014            will be destroyed so the banner won't appear */
4015         modest_platform_information_banner (NULL, NULL, message);
4016
4017         if (account)
4018                 g_object_unref (account);
4019         if (mem_full)
4020                 g_free (message);
4021 }
4022
4023 typedef struct {
4024         TnyFolderStore *folder;
4025         gchar *new_name;
4026 } RenameFolderInfo;
4027
4028 static void
4029 on_rename_folder_cb (ModestMailOperation *mail_op,
4030                      TnyFolder *new_folder,
4031                      gpointer user_data)
4032 {
4033         ModestFolderView *folder_view;
4034
4035         /* If the window was closed when renaming a folder, or if
4036          * it's not a main window this will happen */
4037         if (!MODEST_IS_FOLDER_VIEW (user_data))
4038                 return;
4039
4040         folder_view = MODEST_FOLDER_VIEW (user_data);
4041         /* Note that if the rename fails new_folder will be NULL */
4042         if (new_folder) {
4043                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
4044         } else {
4045                 modest_folder_view_select_first_inbox_or_local (folder_view);
4046         }
4047         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
4048 }
4049
4050 static void
4051 on_rename_folder_performer (gboolean canceled,
4052                             GError *err,
4053                             GtkWindow *parent_window,
4054                             TnyAccount *account,
4055                             gpointer user_data)
4056 {
4057         ModestMailOperation *mail_op = NULL;
4058         GtkTreeSelection *sel = NULL;
4059         GtkWidget *folder_view = NULL;
4060         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
4061
4062         if (canceled || err) {
4063                 /* In disk full conditions we could get this error here */
4064                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4065                                                                 (GtkWidget *) parent_window, err,
4066                                                                 account, NULL);
4067         } else {
4068
4069                 mail_op =
4070                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4071                                         modest_ui_actions_rename_folder_error_handler,
4072                                         parent_window, NULL);
4073
4074                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4075                                 mail_op);
4076
4077                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
4078
4079                         folder_view = modest_main_window_get_child_widget (
4080                                 MODEST_MAIN_WINDOW (parent_window),
4081                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4082                 }
4083 #ifdef MODEST_TOOLKIT_HILDON2
4084                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
4085                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
4086                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
4087                 }
4088 #endif
4089
4090                 /* Clear the folders view */
4091                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4092                 gtk_tree_selection_unselect_all (sel);
4093
4094                 /* Actually rename the folder */
4095                 modest_mail_operation_rename_folder (mail_op,
4096                                                      TNY_FOLDER (data->folder),
4097                                                      (const gchar *) (data->new_name),
4098                                                      on_rename_folder_cb,
4099                                                      folder_view);
4100                 g_object_unref (mail_op);
4101         }
4102
4103         g_object_unref (data->folder);
4104         g_free (data->new_name);
4105         g_free (data);
4106 }
4107
4108 void
4109 modest_ui_actions_on_rename_folder (GtkAction *action,
4110                                      ModestWindow *window)
4111 {
4112         modest_ui_actions_on_edit_mode_rename_folder (window);
4113 }
4114
4115 gboolean
4116 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
4117 {
4118         TnyFolderStore *folder;
4119         GtkWidget *folder_view;
4120         gboolean do_rename = TRUE;
4121
4122         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
4123
4124         if (MODEST_IS_MAIN_WINDOW (window)) {
4125                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4126                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4127                 if (!folder_view)
4128                         return FALSE;
4129
4130 #ifdef MODEST_TOOLKIT_HILDON2
4131         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
4132                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
4133 #endif
4134         } else {
4135                 return FALSE;
4136         }
4137
4138         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
4139
4140         if (!folder)
4141                 return FALSE;
4142
4143         if (TNY_IS_FOLDER (folder)) {
4144                 gchar *folder_name = NULL;
4145                 gint response;
4146                 const gchar *current_name;
4147                 TnyFolderStore *parent;
4148
4149                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
4150                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
4151                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
4152                                                                      parent, current_name,
4153                                                                      &folder_name);
4154                 g_object_unref (parent);
4155
4156                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
4157                         do_rename = FALSE;
4158                 } else {
4159                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
4160                         rename_folder_data->folder = g_object_ref (folder);
4161                         rename_folder_data->new_name = folder_name;
4162                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
4163                                         folder, on_rename_folder_performer, rename_folder_data);
4164                 }
4165         }
4166         g_object_unref (folder);
4167         return do_rename;
4168 }
4169
4170 static void
4171 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
4172                                                gpointer user_data)
4173 {
4174         GObject *win = modest_mail_operation_get_source (mail_op);
4175
4176         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
4177                                                 _("mail_in_ui_folder_delete_error"),
4178                                                 FALSE);
4179         g_object_unref (win);
4180 }
4181
4182 typedef struct {
4183         TnyFolderStore *folder;
4184         gboolean move_to_trash;
4185 } DeleteFolderInfo;
4186
4187 static void
4188 on_delete_folder_cb (gboolean canceled,
4189                   GError *err,
4190                   GtkWindow *parent_window,
4191                   TnyAccount *account,
4192                   gpointer user_data)
4193 {
4194         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
4195         GtkWidget *folder_view;
4196         ModestMailOperation *mail_op;
4197         GtkTreeSelection *sel;
4198
4199         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
4200                 /* Note that the connection process can fail due to
4201                    memory low conditions as it can not successfully
4202                    store the summary */
4203                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4204                                                                      (GtkWidget*) parent_window, err,
4205                                                                      account, NULL))
4206                         g_debug ("Error connecting when trying to delete a folder");
4207                 g_object_unref (G_OBJECT (info->folder));
4208                 g_free (info);
4209                 return;
4210         }
4211
4212         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
4213                 folder_view = modest_main_window_get_child_widget (
4214                         MODEST_MAIN_WINDOW (parent_window),
4215                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4216 #ifdef MODEST_TOOLKIT_HILDON2
4217         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
4218                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
4219 #endif
4220         } else {
4221                 g_object_unref (G_OBJECT (info->folder));
4222                 g_free (info);
4223                 return;
4224         }
4225
4226         /* Unselect the folder before deleting it to free the headers */
4227         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4228         gtk_tree_selection_unselect_all (sel);
4229
4230         /* Create the mail operation */
4231         mail_op =
4232                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4233                                 modest_ui_actions_delete_folder_error_handler,
4234                                 NULL, NULL);
4235
4236         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4237                         mail_op);
4238         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
4239
4240         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
4241
4242         g_object_unref (mail_op);
4243         g_object_unref (info->folder);
4244         g_free (info);
4245 }
4246
4247 static gboolean
4248 delete_folder (ModestWindow *window, gboolean move_to_trash)
4249 {
4250         TnyFolderStore *folder;
4251         GtkWidget *folder_view;
4252         gint response;
4253         gchar *message;
4254
4255         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
4256
4257         if (MODEST_IS_MAIN_WINDOW (window)) {
4258
4259                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4260                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4261 #ifdef MODEST_TOOLKIT_HILDON2
4262         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
4263                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
4264 #endif
4265         } else {
4266                 return FALSE;
4267         }
4268         if (!folder_view)
4269                 return FALSE;
4270
4271         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4272
4273         if (!folder)
4274                 return FALSE;
4275
4276         /* Show an error if it's an account */
4277         if (!TNY_IS_FOLDER (folder)) {
4278                 modest_platform_run_information_dialog (GTK_WINDOW (window),
4279                                                         _("mail_in_ui_folder_delete_error"),
4280                                                         FALSE);
4281                 g_object_unref (G_OBJECT (folder));
4282                 return FALSE;
4283         }
4284
4285         /* Ask the user */
4286         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
4287                                     tny_folder_get_name (TNY_FOLDER (folder)));
4288         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
4289                                                             (const gchar *) message);
4290         g_free (message);
4291
4292         if (response == GTK_RESPONSE_OK) {
4293                 TnyAccount *account = NULL;
4294                 DeleteFolderInfo *info = NULL;
4295                 info = g_new0(DeleteFolderInfo, 1);
4296                 info->folder = g_object_ref (folder);
4297                 info->move_to_trash = move_to_trash;
4298
4299                 account = tny_folder_get_account (TNY_FOLDER (folder));
4300                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
4301                                                                TRUE,
4302                                                                TNY_FOLDER_STORE (account),
4303                                                                on_delete_folder_cb, info);
4304                 g_object_unref (account);
4305                 g_object_unref (folder);
4306                 return TRUE;
4307         } else {
4308                 return FALSE;
4309         }
4310 }
4311
4312 void
4313 modest_ui_actions_on_delete_folder (GtkAction *action,
4314                                     ModestWindow *window)
4315 {
4316         modest_ui_actions_on_edit_mode_delete_folder (window);
4317 }
4318
4319 gboolean
4320 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
4321 {
4322         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
4323
4324         return delete_folder (window, FALSE);
4325 }
4326
4327 void
4328 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4329 {
4330         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4331
4332         delete_folder (MODEST_WINDOW (main_window), TRUE);
4333 }
4334
4335
4336 typedef struct _PasswordDialogFields {
4337         GtkWidget *username;
4338         GtkWidget *password;
4339         GtkWidget *dialog;
4340 } PasswordDialogFields;
4341
4342 static void
4343 password_dialog_check_field (GtkEditable *editable,
4344                              PasswordDialogFields *fields)
4345 {
4346         const gchar *value;
4347         gboolean any_value_empty = FALSE;
4348
4349 #ifdef MODEST_TOOLKIT_HILDON2
4350         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
4351 #else
4352         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
4353 #endif
4354         if ((value == NULL) || value[0] == '\0') {
4355                 any_value_empty = TRUE;
4356         }
4357 #ifdef MODEST_TOOLKIT_HILDON2
4358         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
4359 #else
4360         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
4361 #endif
4362         if ((value == NULL) || value[0] == '\0') {
4363                 any_value_empty = TRUE;
4364         }
4365         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4366 }
4367
4368 void
4369 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4370                                          const gchar* server_account_name,
4371                                          gchar **username,
4372                                          gchar **password,
4373                                          gboolean *cancel,
4374                                          gboolean *remember,
4375                                          ModestMainWindow *main_window)
4376 {
4377         g_return_if_fail(server_account_name);
4378         gboolean completed = FALSE;
4379         PasswordDialogFields *fields = NULL;
4380
4381         /* Initalize output parameters: */
4382         if (cancel)
4383                 *cancel = FALSE;
4384
4385         if (remember)
4386                 *remember = TRUE;
4387
4388 #ifndef MODEST_TOOLKIT_GTK
4389         /* Maemo uses a different (awkward) button order,
4390          * It should probably just use gtk_alternative_dialog_button_order ().
4391          */
4392 #ifdef MODEST_TOOLKIT_HILDON2
4393         GtkWidget *dialog =
4394                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4395                                              NULL,
4396                                              GTK_DIALOG_MODAL,
4397                                              _HL("wdgt_bd_done"),
4398                                              GTK_RESPONSE_ACCEPT,
4399                                              NULL);
4400         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4401                                         HILDON_MARGIN_DOUBLE);
4402 #else
4403         GtkWidget *dialog =
4404                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4405                                              NULL,
4406                                              GTK_DIALOG_MODAL,
4407                                              _("mcen_bd_dialog_ok"),
4408                                              GTK_RESPONSE_ACCEPT,
4409                                              _("mcen_bd_dialog_cancel"),
4410                                              GTK_RESPONSE_REJECT,
4411                                              NULL);
4412 #endif /* MODEST_TOOLKIT_HILDON2 */
4413 #else
4414         GtkWidget *dialog =
4415                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4416                                              NULL,
4417                                              GTK_DIALOG_MODAL,
4418                                              GTK_STOCK_CANCEL,
4419                                              GTK_RESPONSE_REJECT,
4420                                              GTK_STOCK_OK,
4421                                              GTK_RESPONSE_ACCEPT,
4422                                              NULL);
4423 #endif /* MODEST_TOOLKIT_GTK */
4424
4425         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4426
4427         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4428                 modest_runtime_get_account_mgr(), server_account_name);
4429         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4430                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4431                 if (cancel)
4432                         *cancel = TRUE;
4433                 gtk_widget_destroy (dialog);
4434                 return;
4435         }
4436
4437         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4438         GtkWidget *label = gtk_label_new (txt);
4439         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4440         g_free (txt);
4441         g_free (server_name);
4442         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4443                             FALSE, FALSE, 0);
4444         server_name = NULL;
4445
4446         /* username: */
4447         gchar *initial_username = modest_account_mgr_get_server_account_username (
4448                 modest_runtime_get_account_mgr(), server_account_name);
4449
4450 #ifdef MODEST_TOOLKIT_HILDON2
4451         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4452         if (initial_username)
4453                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4454 #else
4455         GtkWidget *entry_username = gtk_entry_new ();
4456         if (initial_username)
4457                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4458 #endif
4459         /* Dim this if a connection has ever succeeded with this username,
4460          * as per the UI spec: */
4461         /* const gboolean username_known =  */
4462         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4463         /*              modest_runtime_get_account_mgr(), server_account_name); */
4464         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4465
4466         /* We drop the username sensitive code and disallow changing it here
4467          * as tinymail does not support really changing the username in the callback
4468          */
4469         gtk_widget_set_sensitive (entry_username, FALSE);
4470
4471 #ifndef MODEST_TOOLKIT_GTK
4472         /* Auto-capitalization is the default, so let's turn it off: */
4473         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4474
4475         /* Create a size group to be used by all captions.
4476          * Note that HildonCaption does not create a default size group if we do not specify one.
4477          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4478         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4479
4480 #ifdef MODEST_TOOLKIT_HILDON2
4481         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4482                                                                   _("mail_fi_username"), FALSE,
4483                                                                   entry_username);
4484 #else
4485         GtkWidget *caption = hildon_caption_new (sizegroup,
4486                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4487 #endif
4488         gtk_widget_show (entry_username);
4489         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4490                 FALSE, FALSE, MODEST_MARGIN_HALF);
4491         gtk_widget_show (caption);
4492 #else
4493         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4494                             TRUE, FALSE, 0);
4495 #endif /* !MODEST_TOOLKIT_GTK */
4496
4497         /* password: */
4498 #ifdef MODEST_TOOLKIT_HILDON2
4499         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4500 #else
4501         GtkWidget *entry_password = gtk_entry_new ();
4502 #endif
4503         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4504         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4505
4506 #ifndef MODEST_TOOLKIT_GTK
4507         /* Auto-capitalization is the default, so let's turn it off: */
4508         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4509                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4510
4511 #ifdef MODEST_TOOLKIT_HILDON2
4512         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4513                                                        _("mail_fi_password"), FALSE,
4514                                                        entry_password);
4515 #else
4516         caption = hildon_caption_new (sizegroup,
4517                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4518 #endif
4519         gtk_widget_show (entry_password);
4520         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4521                 FALSE, FALSE, MODEST_MARGIN_HALF);
4522         gtk_widget_show (caption);
4523         g_object_unref (sizegroup);
4524 #else
4525         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4526                             TRUE, FALSE, 0);
4527 #endif /* !MODEST_TOOLKIT_GTK */
4528
4529         if (initial_username != NULL)
4530                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4531
4532 /* This is not in the Maemo UI spec:
4533         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4534         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4535                             TRUE, FALSE, 0);
4536 */
4537
4538         fields = g_slice_new0 (PasswordDialogFields);
4539         fields->username = entry_username;
4540         fields->password = entry_password;
4541         fields->dialog = dialog;
4542
4543         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4544         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4545         password_dialog_check_field (NULL, fields);
4546
4547         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4548
4549         while (!completed) {
4550
4551                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4552                         if (username) {
4553 #ifdef MODEST_TOOLKIT_HILDON2
4554                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4555 #else
4556                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4557 #endif
4558
4559                                 /* Note that an empty field becomes the "" string */
4560                                 if (*username && strlen (*username) > 0) {
4561                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4562                                                                                         server_account_name,
4563                                                                                         *username);
4564                                         completed = TRUE;
4565
4566                                         const gboolean username_was_changed =
4567                                                 (strcmp (*username, initial_username) != 0);
4568                                         if (username_was_changed) {
4569                                                 g_warning ("%s: tinymail does not yet support changing the "
4570                                                            "username in the get_password() callback.\n", __FUNCTION__);
4571                                         }
4572                                 } else {
4573                                         g_free (*username);
4574                                         *username = NULL;
4575                                         /* Show error */
4576                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4577                                                                             _("mcen_ib_username_pw_incorrect"));
4578                                         completed = FALSE;
4579                                 }
4580                         }
4581
4582                         if (password) {
4583 #ifdef MODEST_TOOLKIT_HILDON2
4584                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4585 #else
4586                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4587 #endif
4588
4589                                 /* We do not save the password in the configuration,
4590                                  * because this function is only called for passwords that should
4591                                  * not be remembered:
4592                                  modest_server_account_set_password (
4593                                  modest_runtime_get_account_mgr(), server_account_name,
4594                                  *password);
4595                                  */
4596                         }
4597                         if (cancel)
4598                                 *cancel   = FALSE;
4599                 } else {
4600 #ifndef MODEST_TOOLKIT_HILDON2
4601                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4602                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4603 #endif
4604                         completed = TRUE;
4605                         if (username)
4606                                 *username = NULL;
4607                         if (password)
4608                                 *password = NULL;
4609                         if (cancel)
4610                                 *cancel   = TRUE;
4611                 }
4612         }
4613
4614 /* This is not in the Maemo UI spec:
4615         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4616                 *remember = TRUE;
4617         else
4618                 *remember = FALSE;
4619 */
4620
4621         g_free (initial_username);
4622         gtk_widget_destroy (dialog);
4623         g_slice_free (PasswordDialogFields, fields);
4624
4625         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4626 }
4627
4628 void
4629 modest_ui_actions_on_cut (GtkAction *action,
4630                           ModestWindow *window)
4631 {
4632         GtkWidget *focused_widget;
4633         GtkClipboard *clipboard;
4634
4635         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4636         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4637         if (GTK_IS_EDITABLE (focused_widget)) {
4638                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4639                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4640                 gtk_clipboard_store (clipboard);
4641         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4642                 GtkTextBuffer *buffer;
4643
4644                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4645                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4646                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4647                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4648                         gtk_clipboard_store (clipboard);
4649                 }
4650         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4651                 TnyList *header_list = modest_header_view_get_selected_headers (
4652                                 MODEST_HEADER_VIEW (focused_widget));
4653                 gboolean continue_download = FALSE;
4654                 gint num_of_unc_msgs;
4655
4656                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4657
4658                 if (num_of_unc_msgs) {
4659                         TnyAccount *account = get_account_from_header_list (header_list);
4660                         if (account) {
4661                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4662                                 g_object_unref (account);
4663                         }
4664                 }
4665
4666                 if (num_of_unc_msgs == 0 || continue_download) {
4667 /*                      modest_platform_information_banner (
4668                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4669                         modest_header_view_cut_selection (
4670                                         MODEST_HEADER_VIEW (focused_widget));
4671                 }
4672
4673                 g_object_unref (header_list);
4674         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4675                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4676         }
4677 }
4678
4679 void
4680 modest_ui_actions_on_copy (GtkAction *action,
4681                            ModestWindow *window)
4682 {
4683         GtkClipboard *clipboard;
4684         GtkWidget *focused_widget;
4685         gboolean copied = TRUE;
4686
4687         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4688         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4689
4690         if (GTK_IS_LABEL (focused_widget)) {
4691                 gchar *selection;
4692                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4693                 gtk_clipboard_set_text (clipboard, selection, -1);
4694                 g_free (selection);
4695                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4696                 gtk_clipboard_store (clipboard);
4697         } else if (GTK_IS_EDITABLE (focused_widget)) {
4698                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4699                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4700                 gtk_clipboard_store (clipboard);
4701         } else if (GTK_IS_HTML (focused_widget)) {
4702                 const gchar *sel;
4703                 int len = -1;
4704                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4705                 if ((sel == NULL) || (sel[0] == '\0')) {
4706                         copied = FALSE;
4707                 } else {
4708                         gtk_html_copy (GTK_HTML (focused_widget));
4709                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4710                         gtk_clipboard_store (clipboard);
4711                 }
4712         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4713                 GtkTextBuffer *buffer;
4714                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4715                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4716                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4717                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4718                         gtk_clipboard_store (clipboard);
4719                 }
4720         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4721                 TnyList *header_list = modest_header_view_get_selected_headers (
4722                                 MODEST_HEADER_VIEW (focused_widget));
4723                 gboolean continue_download = FALSE;
4724                 gint num_of_unc_msgs;
4725
4726                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4727
4728                 if (num_of_unc_msgs) {
4729                         TnyAccount *account = get_account_from_header_list (header_list);
4730                         if (account) {
4731                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4732                                 g_object_unref (account);
4733                         }
4734                 }
4735
4736                 if (num_of_unc_msgs == 0 || continue_download) {
4737                         modest_platform_information_banner (
4738                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4739                         modest_header_view_copy_selection (
4740                                         MODEST_HEADER_VIEW (focused_widget));
4741                 } else
4742                         copied = FALSE;
4743
4744                 g_object_unref (header_list);
4745
4746         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4747                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4748         }
4749
4750         /* Show information banner if there was a copy to clipboard */
4751         if(copied)
4752                 modest_platform_information_banner (
4753                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4754 }
4755
4756 void
4757 modest_ui_actions_on_undo (GtkAction *action,
4758                            ModestWindow *window)
4759 {
4760         ModestEmailClipboard *clipboard = NULL;
4761
4762         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4763                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4764         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4765                 /* Clear clipboard source */
4766                 clipboard = modest_runtime_get_email_clipboard ();
4767                 modest_email_clipboard_clear (clipboard);
4768         }
4769         else {
4770                 g_return_if_reached ();
4771         }
4772 }
4773
4774 void
4775 modest_ui_actions_on_redo (GtkAction *action,
4776                            ModestWindow *window)
4777 {
4778         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4779                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4780         }
4781         else {
4782                 g_return_if_reached ();
4783         }
4784 }
4785
4786
4787 static void
4788 destroy_information_note (ModestMailOperation *mail_op,
4789                           gpointer user_data)
4790 {
4791         /* destroy information note */
4792         gtk_widget_destroy (GTK_WIDGET(user_data));
4793 }
4794
4795 static void
4796 destroy_folder_information_note (ModestMailOperation *mail_op,
4797                                  TnyFolder *new_folder,
4798                                  gpointer user_data)
4799 {
4800         /* destroy information note */
4801         gtk_widget_destroy (GTK_WIDGET(user_data));
4802 }
4803
4804
4805 static void
4806 paste_as_attachment_free (gpointer data)
4807 {
4808         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4809
4810         if (helper->banner) {
4811                 gtk_widget_destroy (helper->banner);
4812                 g_object_unref (helper->banner);
4813         }
4814         g_free (helper);
4815 }
4816
4817 static void
4818 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4819                             TnyHeader *header,
4820                             TnyMsg *msg,
4821                             gpointer userdata)
4822 {
4823         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4824         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4825
4826         if (msg == NULL)
4827                 return;
4828
4829         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4830
4831 }
4832
4833 void
4834 modest_ui_actions_on_paste (GtkAction *action,
4835                             ModestWindow *window)
4836 {
4837         GtkWidget *focused_widget = NULL;
4838         GtkWidget *inf_note = NULL;
4839         ModestMailOperation *mail_op = NULL;
4840
4841         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4842         if (GTK_IS_EDITABLE (focused_widget)) {
4843                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4844         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4845                 ModestEmailClipboard *e_clipboard = NULL;
4846                 e_clipboard = modest_runtime_get_email_clipboard ();
4847                 if (modest_email_clipboard_cleared (e_clipboard)) {
4848                         GtkTextBuffer *buffer;
4849                         GtkClipboard *clipboard;
4850
4851                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4852                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4853                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4854                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4855                         ModestMailOperation *mail_op;
4856                         TnyFolder *src_folder = NULL;
4857                         TnyList *data = NULL;
4858                         gboolean delete;
4859                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4860                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4861                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4862                                                                            _CS("ckct_nw_pasting"));
4863                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4864                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4865                         if (helper->banner != NULL) {
4866                                 g_object_ref (G_OBJECT (helper->banner));
4867                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4868                         }
4869
4870                         if (data != NULL) {
4871                                 modest_mail_operation_get_msgs_full (mail_op,
4872                                                                      data,
4873                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4874                                                                      helper,
4875                                                                      paste_as_attachment_free);
4876                         }
4877                         /* Free */
4878                         if (data)
4879                                 g_object_unref (data);
4880                         if (src_folder)
4881                                 g_object_unref (src_folder);
4882
4883                 }
4884         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4885                 ModestEmailClipboard *clipboard = NULL;
4886                 TnyFolder *src_folder = NULL;
4887                 TnyFolderStore *folder_store = NULL;
4888                 TnyList *data = NULL;
4889                 gboolean delete = FALSE;
4890
4891                 /* Check clipboard source */
4892                 clipboard = modest_runtime_get_email_clipboard ();
4893                 if (modest_email_clipboard_cleared (clipboard))
4894                         return;
4895
4896                 /* Get elements to paste */
4897                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4898
4899                 /* Create a new mail operation */
4900                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4901
4902                 /* Get destination folder */
4903                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4904
4905                 /* transfer messages  */
4906                 if (data != NULL) {
4907                         gint response = 0;
4908
4909                         /* Ask for user confirmation */
4910                         response =
4911                                 modest_ui_actions_msgs_move_to_confirmation (window,
4912                                                                              TNY_FOLDER (folder_store),
4913                                                                              delete,
4914                                                                              data);
4915
4916                         if (response == GTK_RESPONSE_OK) {
4917                                 /* Launch notification */
4918                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4919                                                                              _CS("ckct_nw_pasting"));
4920                                 if (inf_note != NULL)  {
4921                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4922                                         gtk_widget_show (GTK_WIDGET(inf_note));
4923                                 }
4924
4925                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4926                                 modest_mail_operation_xfer_msgs (mail_op,
4927                                                                  data,
4928                                                                  TNY_FOLDER (folder_store),
4929                                                                  delete,
4930                                                                  destroy_information_note,
4931                                                                  inf_note);
4932                         } else {
4933                                 g_object_unref (mail_op);
4934                         }
4935
4936                 } else if (src_folder != NULL) {
4937                         /* Launch notification */
4938                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4939                                                                      _CS("ckct_nw_pasting"));
4940                         if (inf_note != NULL)  {
4941                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4942                                 gtk_widget_show (GTK_WIDGET(inf_note));
4943                         }
4944
4945                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4946                         modest_mail_operation_xfer_folder (mail_op,
4947                                                            src_folder,
4948                                                            folder_store,
4949                                                            delete,
4950                                                            destroy_folder_information_note,
4951                                                            inf_note);
4952                 }
4953
4954                 /* Free */
4955                 if (data != NULL)
4956                         g_object_unref (data);
4957                 if (src_folder != NULL)
4958                         g_object_unref (src_folder);
4959                 if (folder_store != NULL)
4960                         g_object_unref (folder_store);
4961         }
4962 }
4963
4964
4965 void
4966 modest_ui_actions_on_select_all (GtkAction *action,
4967                                  ModestWindow *window)
4968 {
4969         GtkWidget *focused_widget;
4970
4971         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4972         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4973                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4974         } else if (GTK_IS_LABEL (focused_widget)) {
4975                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4976         } else if (GTK_IS_EDITABLE (focused_widget)) {
4977                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4978         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4979                 GtkTextBuffer *buffer;
4980                 GtkTextIter start, end;
4981
4982                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4983                 gtk_text_buffer_get_start_iter (buffer, &start);
4984                 gtk_text_buffer_get_end_iter (buffer, &end);
4985                 gtk_text_buffer_select_range (buffer, &start, &end);
4986         } else if (GTK_IS_HTML (focused_widget)) {
4987                 gtk_html_select_all (GTK_HTML (focused_widget));
4988         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4989                 GtkWidget *header_view = focused_widget;
4990                 GtkTreeSelection *selection = NULL;
4991
4992                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4993                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4994                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4995                 }
4996
4997                 /* Disable window dimming management */
4998                 modest_window_disable_dimming (MODEST_WINDOW(window));
4999
5000                 /* Select all messages */
5001                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
5002                 gtk_tree_selection_select_all (selection);
5003
5004                 /* Set focuse on header view */
5005                 gtk_widget_grab_focus (header_view);
5006
5007                 /* Enable window dimming management */
5008                 modest_window_enable_dimming (MODEST_WINDOW(window));
5009                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
5010                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
5011         }
5012
5013 }
5014
5015 void
5016 modest_ui_actions_on_mark_as_read (GtkAction *action,
5017                                    ModestWindow *window)
5018 {
5019         g_return_if_fail (MODEST_IS_WINDOW(window));
5020
5021         /* Mark each header as read */
5022         do_headers_action (window, headers_action_mark_as_read, NULL);
5023 }
5024
5025 void
5026 modest_ui_actions_on_mark_as_unread (GtkAction *action,
5027                                      ModestWindow *window)
5028 {
5029         g_return_if_fail (MODEST_IS_WINDOW(window));
5030
5031         /* Mark each header as read */
5032         do_headers_action (window, headers_action_mark_as_unread, NULL);
5033 }
5034
5035 void
5036 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
5037                                   GtkRadioAction *selected,
5038                                   ModestWindow *window)
5039 {
5040         gint value;
5041
5042         value = gtk_radio_action_get_current_value (selected);
5043         if (MODEST_IS_WINDOW (window)) {
5044                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
5045         }
5046 }
5047
5048 void
5049 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
5050                                                GtkRadioAction *selected,
5051                                                ModestWindow *window)
5052 {
5053         TnyHeaderFlags flags;
5054         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5055
5056         flags = gtk_radio_action_get_current_value (selected);
5057         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
5058 }
5059
5060 void
5061 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
5062                                                   GtkRadioAction *selected,
5063                                                   ModestWindow *window)
5064 {
5065         gint file_format;
5066
5067         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5068
5069         file_format = gtk_radio_action_get_current_value (selected);
5070         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
5071 }
5072
5073
5074 void
5075 modest_ui_actions_on_zoom_plus (GtkAction *action,
5076                                 ModestWindow *window)
5077 {
5078         g_return_if_fail (MODEST_IS_WINDOW (window));
5079
5080         modest_window_zoom_plus (MODEST_WINDOW (window));
5081 }
5082
5083 void
5084 modest_ui_actions_on_zoom_minus (GtkAction *action,
5085                                  ModestWindow *window)
5086 {
5087         g_return_if_fail (MODEST_IS_WINDOW (window));
5088
5089         modest_window_zoom_minus (MODEST_WINDOW (window));
5090 }
5091
5092 void
5093 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
5094                                            ModestWindow *window)
5095 {
5096         ModestWindowMgr *mgr;
5097         gboolean fullscreen, active;
5098         g_return_if_fail (MODEST_IS_WINDOW (window));
5099
5100         mgr = modest_runtime_get_window_mgr ();
5101
5102         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
5103         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
5104
5105         if (active != fullscreen) {
5106                 modest_window_mgr_set_fullscreen_mode (mgr, active);
5107 #ifndef MODEST_TOOLKIT_HILDON2
5108                 gtk_window_present (GTK_WINDOW (window));
5109 #endif
5110         }
5111 }
5112
5113 void
5114 modest_ui_actions_on_change_fullscreen (GtkAction *action,
5115                                         ModestWindow *window)
5116 {
5117         ModestWindowMgr *mgr;
5118         gboolean fullscreen;
5119
5120         g_return_if_fail (MODEST_IS_WINDOW (window));
5121
5122         mgr = modest_runtime_get_window_mgr ();
5123         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
5124         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
5125
5126 #ifndef MODEST_TOOLKIT_HILDON2
5127         gtk_window_present (GTK_WINDOW (window));
5128 #endif
5129 }
5130
5131 /*
5132  * Used by modest_ui_actions_on_details to call do_headers_action
5133  */
5134 static void
5135 headers_action_show_details (TnyHeader *header,
5136                              ModestWindow *window,
5137                              gpointer user_data)
5138
5139 {
5140         gboolean async_retrieval;
5141         TnyMsg *msg = NULL;
5142
5143         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5144                 async_retrieval = TRUE;
5145                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
5146                 async_retrieval = !TNY_IS_CAMEL_BS_MSG (msg);
5147         } else {
5148                 async_retrieval = FALSE;
5149         }
5150         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
5151         if (msg)
5152                 g_object_unref (msg);
5153 }
5154
5155 /*
5156  * Show the header details in a ModestDetailsDialog widget
5157  */
5158 void
5159 modest_ui_actions_on_details (GtkAction *action,
5160                               ModestWindow *win)
5161 {
5162         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5163                 TnyMsg *msg;
5164                 TnyHeader *header;
5165
5166                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
5167                 if (!msg)
5168                         return;
5169
5170                 header = tny_msg_get_header (msg);
5171                 if (header) {
5172                         headers_action_show_details (header, win, NULL);
5173                         g_object_unref (header);
5174                 }
5175                 g_object_unref (msg);
5176
5177         } else if (MODEST_IS_MAIN_WINDOW (win)) {
5178                 GtkWidget *folder_view, *header_view;
5179
5180                 /* Check which widget has the focus */
5181                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5182                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5183                 if (gtk_widget_is_focus (folder_view)) {
5184                         TnyFolderStore *folder_store
5185                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5186                         if (!folder_store) {
5187                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
5188                                 return;
5189                         }
5190                         /* Show only when it's a folder */
5191                         /* This function should not be called for account items,
5192                          * because we dim the menu item for them. */
5193                         if (TNY_IS_FOLDER (folder_store)) {
5194                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
5195                                                                            TNY_FOLDER (folder_store));
5196                         }
5197
5198                         g_object_unref (folder_store);
5199
5200                 } else {
5201                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5202                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5203                         /* Show details of each header */
5204                         do_headers_action (win, headers_action_show_details, header_view);
5205                 }
5206 #ifdef MODEST_TOOLKIT_HILDON2
5207         } else if (MODEST_IS_HEADER_WINDOW (win)) {
5208                 TnyFolder *folder;
5209                 GtkWidget *header_view;
5210
5211                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
5212                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
5213                 if (folder) {
5214                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
5215                                                                    folder);
5216                         g_object_unref (folder);
5217                 }
5218 #endif
5219         }
5220 }
5221
5222 void
5223 modest_ui_actions_on_limit_error (GtkAction *action,
5224                                   ModestWindow *win)
5225 {
5226         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
5227
5228         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
5229
5230 }
5231
5232 void
5233 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
5234                                      ModestMsgEditWindow *window)
5235 {
5236         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5237
5238         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
5239 }
5240
5241 void
5242 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
5243                                       ModestMsgEditWindow *window)
5244 {
5245         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5246
5247         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
5248 }
5249
5250 void
5251 modest_ui_actions_toggle_folders_view (GtkAction *action,
5252                                        ModestMainWindow *main_window)
5253 {
5254         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
5255
5256         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
5257                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
5258         else
5259                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
5260 }
5261
5262 void
5263 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
5264                                      ModestWindow *window)
5265 {
5266         gboolean active, fullscreen = FALSE;
5267         ModestWindowMgr *mgr;
5268
5269         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
5270
5271         /* Check if we want to toggle the toolbar view in fullscreen
5272            or normal mode */
5273         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
5274                      "ViewShowToolbarFullScreen")) {
5275                 fullscreen = TRUE;
5276         }
5277
5278         /* Toggle toolbar */
5279         mgr = modest_runtime_get_window_mgr ();
5280         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
5281 }
5282
5283 void
5284 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
5285                                            ModestMsgEditWindow *window)
5286 {
5287         modest_msg_edit_window_select_font (window);
5288 }
5289
5290
5291 void
5292 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
5293                                                   const gchar *display_name,
5294                                                   GtkWindow *window)
5295 {
5296         /* don't update the display name if it was already set;
5297          * updating the display name apparently is expensive */
5298         const gchar* old_name = gtk_window_get_title (window);
5299
5300         if (display_name == NULL)
5301                 display_name = " ";
5302
5303         if (old_name && display_name && strcmp (old_name, display_name) == 0)
5304                 return; /* don't do anything */
5305
5306         /* This is usually used to change the title of the main window, which
5307          * is the one that holds the folder view. Note that this change can
5308          * happen even when the widget doesn't have the focus. */
5309         gtk_window_set_title (window, display_name);
5310
5311 }
5312
5313 void
5314 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
5315 {
5316         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5317         modest_msg_edit_window_select_contacts (window);
5318 }
5319
5320 void
5321 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
5322 {
5323         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5324         modest_msg_edit_window_check_names (window, FALSE);
5325 }
5326
5327 #ifndef MODEST_TOOLKIT_HILDON2
5328 /*
5329  * This function is used to track changes in the selection of the
5330  * folder view that is inside the "move to" dialog to enable/disable
5331  * the OK button because we do not want the user to select a disallowed
5332  * destination for a folder.
5333  * The user also not desired to be able to use NEW button on items where
5334  * folder creation is not possibel.
5335  */
5336 static void
5337 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
5338                                             TnyFolderStore *folder_store,
5339                                             gboolean selected,
5340                                             gpointer user_data)
5341 {
5342         GtkWidget *dialog = NULL;
5343         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
5344         gboolean moving_folder = FALSE;
5345         gboolean is_local_account = TRUE;
5346         GtkWidget *folder_view = NULL;
5347         ModestTnyFolderRules rules;
5348
5349         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
5350
5351         if (!selected)
5352                 return;
5353
5354         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5355         if (!dialog)
5356                 return;
5357
5358         /* check if folder_store is an remote account */
5359         if (TNY_IS_ACCOUNT (folder_store)) {
5360                 TnyAccount *local_account = NULL;
5361                 TnyAccount *mmc_account = NULL;
5362                 ModestTnyAccountStore *account_store = NULL;
5363
5364                 account_store = modest_runtime_get_account_store ();
5365                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5366                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5367
5368                 if ((gpointer) local_account != (gpointer) folder_store &&
5369                     (gpointer) mmc_account != (gpointer) folder_store) {
5370                         ModestProtocolType proto;
5371                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5372                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5373                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5374                         }
5375                         is_local_account = FALSE;
5376                         /* New button should be dimmed on remote
5377                            POP account root */
5378                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5379                                                                                          proto,
5380                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5381                 }
5382                 g_object_unref (local_account);
5383
5384                 /* It could not exist */
5385                 if (mmc_account)
5386                         g_object_unref (mmc_account);
5387         }
5388
5389         /* Check the target folder rules */
5390         if (TNY_IS_FOLDER (folder_store)) {
5391                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5392                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5393                         ok_sensitive = FALSE;
5394                         new_sensitive = FALSE;
5395                         goto end;
5396                 }
5397         }
5398
5399         /* Check if we're moving a folder */
5400         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5401                 /* Get the widgets */
5402                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5403                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5404                 if (gtk_widget_is_focus (folder_view))
5405                         moving_folder = TRUE;
5406         }
5407
5408         if (moving_folder) {
5409                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5410
5411                 /* Get the folder to move */
5412                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5413
5414                 /* Check that we're not moving to the same folder */
5415                 if (TNY_IS_FOLDER (moved_folder)) {
5416                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5417                         if (parent == folder_store)
5418                                 ok_sensitive = FALSE;
5419                         g_object_unref (parent);
5420                 }
5421
5422                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5423                         /* Do not allow to move to an account unless it's the
5424                            local folders account */
5425                         if (!is_local_account)
5426                                 ok_sensitive = FALSE;
5427                 }
5428
5429                 if (ok_sensitive && (moved_folder == folder_store)) {
5430                         /* Do not allow to move to itself */
5431                         ok_sensitive = FALSE;
5432                 }
5433                 g_object_unref (moved_folder);
5434         } else {
5435                 TnyFolder *src_folder = NULL;
5436
5437                 /* Moving a message */
5438                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5439
5440                         TnyHeader *header = NULL;
5441                         header = modest_msg_view_window_get_header
5442                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5443                         if (!TNY_IS_HEADER(header))
5444                                 g_warning ("%s: could not get source header", __FUNCTION__);
5445                         else
5446                                 src_folder = tny_header_get_folder (header);
5447
5448                         if (header)
5449                                 g_object_unref (header);
5450                 } else {
5451                         src_folder =
5452                                 TNY_FOLDER (modest_folder_view_get_selected
5453                                             (MODEST_FOLDER_VIEW (folder_view)));
5454                 }
5455
5456                 if (TNY_IS_FOLDER(src_folder)) {
5457                         /* Do not allow to move the msg to the same folder */
5458                         /* Do not allow to move the msg to an account */
5459                         if ((gpointer) src_folder == (gpointer) folder_store ||
5460                             TNY_IS_ACCOUNT (folder_store))
5461                                 ok_sensitive = FALSE;
5462                         g_object_unref (src_folder);
5463                 } else
5464                         g_warning ("%s: could not get source folder", __FUNCTION__);
5465         }
5466
5467  end:
5468         /* Set sensitivity of the OK and NEW button */
5469         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5470         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5471 }
5472 #endif
5473
5474 static void
5475 on_move_to_dialog_response (GtkDialog *dialog,
5476                             gint       response,
5477                             gpointer   user_data)
5478 {
5479         GtkWidget *parent_win;
5480         MoveToInfo *helper = NULL;
5481         ModestFolderView *folder_view;
5482         gboolean unset_edit_mode = FALSE;
5483
5484         helper = (MoveToInfo *) user_data;
5485
5486         parent_win = (GtkWidget *) helper->win;
5487         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5488                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5489         switch (response) {
5490                 TnyFolderStore *dst_folder;
5491                 TnyFolderStore *selected;
5492
5493         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5494                 selected = modest_folder_view_get_selected (folder_view);
5495                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5496                 g_object_unref (selected);
5497                 return;
5498         case GTK_RESPONSE_NONE:
5499         case GTK_RESPONSE_CANCEL:
5500         case GTK_RESPONSE_DELETE_EVENT:
5501                 break;
5502         case GTK_RESPONSE_OK:
5503                 dst_folder = modest_folder_view_get_selected (folder_view);
5504
5505                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5506                         /* Clean list to move used for filtering */
5507                         modest_folder_view_set_list_to_move (folder_view, NULL);
5508
5509                         modest_ui_actions_on_main_window_move_to (NULL,
5510                                                                   GTK_WIDGET (folder_view),
5511                                                                   dst_folder,
5512                                                                   MODEST_MAIN_WINDOW (parent_win));
5513 #ifdef MODEST_TOOLKIT_HILDON2
5514                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5515                         /* Clean list to move used for filtering */
5516                         modest_folder_view_set_list_to_move (folder_view, NULL);
5517
5518                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5519                                                                     dst_folder,
5520                                                                     helper->list,
5521                                                                     GTK_WINDOW (parent_win));
5522 #endif
5523                 } else {
5524                         /* if the user selected a root folder
5525                            (account) then do not perform any action */
5526                         if (TNY_IS_ACCOUNT (dst_folder)) {
5527                                 g_signal_stop_emission_by_name (dialog, "response");
5528                                 return;
5529                         }
5530
5531                         /* Clean list to move used for filtering */
5532                         modest_folder_view_set_list_to_move (folder_view, NULL);
5533
5534                         /* Moving from headers window in edit mode */
5535                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5536                                                              dst_folder,
5537                                                              MODEST_WINDOW (parent_win));
5538                 }
5539
5540                 if (dst_folder)
5541                         g_object_unref (dst_folder);
5542
5543                 unset_edit_mode = TRUE;
5544                 break;
5545         default:
5546                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5547         }
5548
5549         /* Free the helper and exit */
5550         if (helper->list)
5551                 g_object_unref (helper->list);
5552         if (unset_edit_mode) {
5553 #ifdef MODEST_TOOLKIT_HILDON2
5554                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5555 #endif
5556         }
5557         g_slice_free (MoveToInfo, helper);
5558         gtk_widget_destroy (GTK_WIDGET (dialog));
5559 }
5560
5561 static GtkWidget*
5562 create_move_to_dialog (GtkWindow *win,
5563                        GtkWidget *folder_view,
5564                        TnyList *list_to_move)
5565 {
5566         GtkWidget *dialog, *tree_view = NULL;
5567
5568         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5569
5570 #ifndef MODEST_TOOLKIT_HILDON2
5571         /* Track changes in the selection to
5572          * disable the OK button whenever "Move to" is not possible
5573          * disbale NEW button whenever New is not possible */
5574         g_signal_connect (tree_view,
5575                           "folder_selection_changed",
5576                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5577                           win);
5578 #endif
5579
5580         /* It could happen that we're trying to move a message from a
5581            window (msg window for example) after the main window was
5582            closed, so we can not just get the model of the folder
5583            view */
5584         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5585                 const gchar *visible_id = NULL;
5586
5587                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5588                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5589                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5590                                                MODEST_FOLDER_VIEW(tree_view));
5591
5592                 visible_id =
5593                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5594
5595                 /* Show the same account than the one that is shown in the main window */
5596                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5597                                                                              visible_id);
5598         } else {
5599                 const gchar *active_account_name = NULL;
5600                 ModestAccountMgr *mgr = NULL;
5601                 ModestAccountSettings *settings = NULL;
5602                 ModestServerAccountSettings *store_settings = NULL;
5603
5604                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5605                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5606
5607                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5608                 mgr = modest_runtime_get_account_mgr ();
5609                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5610
5611                 if (settings) {
5612                         const gchar *store_account_name;
5613                         store_settings = modest_account_settings_get_store_settings (settings);
5614                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5615
5616                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5617                                                                                      store_account_name);
5618                         g_object_unref (store_settings);
5619                         g_object_unref (settings);
5620                 }
5621         }
5622
5623         /* we keep a pointer to the embedded folder view, so we can
5624          *   retrieve it with get_folder_view_from_move_to_dialog (see
5625          *   above) later (needed for focus handling)
5626          */
5627         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5628
5629         /* Hide special folders */
5630 #ifndef MODEST_TOOLKIT_HILDON2
5631         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5632 #endif
5633         if (list_to_move)
5634                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5635 #ifndef MODEST_TOOLKIT_HILDON2
5636         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5637 #endif
5638
5639         gtk_widget_show (GTK_WIDGET (tree_view));
5640
5641         return dialog;
5642 }
5643
5644 /*
5645  * Shows a confirmation dialog to the user when we're moving messages
5646  * from a remote server to the local storage. Returns the dialog
5647  * response. If it's other kind of movement then it always returns
5648  * GTK_RESPONSE_OK
5649  *
5650  * This one is used by the next functions:
5651  *      modest_ui_actions_on_paste                      - commented out
5652  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5653  */
5654 gint
5655 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5656                                              TnyFolder *dest_folder,
5657                                              gboolean delete,
5658                                              TnyList *headers)
5659 {
5660         gint response = GTK_RESPONSE_OK;
5661         TnyAccount *account = NULL;
5662         TnyFolder *src_folder = NULL;
5663         TnyIterator *iter = NULL;
5664         TnyHeader *header = NULL;
5665
5666         /* return with OK if the destination is a remote folder */
5667         if (modest_tny_folder_is_remote_folder (dest_folder))
5668                 return GTK_RESPONSE_OK;
5669
5670         /* Get source folder */
5671         iter = tny_list_create_iterator (headers);
5672         header = TNY_HEADER (tny_iterator_get_current (iter));
5673         if (header) {
5674                 src_folder = tny_header_get_folder (header);
5675                 g_object_unref (header);
5676         }
5677         g_object_unref (iter);
5678
5679         /* if no src_folder, message may be an attahcment */
5680         if (src_folder == NULL)
5681                 return GTK_RESPONSE_CANCEL;
5682
5683         /* If the source is a local or MMC folder */
5684         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5685                 g_object_unref (src_folder);
5686                 return GTK_RESPONSE_OK;
5687         }
5688
5689         /* Get the account */
5690         account = tny_folder_get_account (src_folder);
5691
5692         /* now if offline we ask the user */
5693         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5694                 response = GTK_RESPONSE_OK;
5695         else
5696                 response = GTK_RESPONSE_CANCEL;
5697
5698         /* Frees */
5699         g_object_unref (src_folder);
5700         g_object_unref (account);
5701
5702         return response;
5703 }
5704
5705 static void
5706 move_to_helper_destroyer (gpointer user_data)
5707 {
5708         MoveToHelper *helper = (MoveToHelper *) user_data;
5709
5710         /* Close the "Pasting" information banner */
5711         if (helper->banner) {
5712                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5713                 g_object_unref (helper->banner);
5714         }
5715         if (gtk_tree_row_reference_valid (helper->reference)) {
5716                 gtk_tree_row_reference_free (helper->reference);
5717                 helper->reference = NULL;
5718         }
5719         g_free (helper);
5720 }
5721
5722 static void
5723 move_to_cb (ModestMailOperation *mail_op,
5724             gpointer user_data)
5725 {
5726         MoveToHelper *helper = (MoveToHelper *) user_data;
5727         GObject *object = modest_mail_operation_get_source (mail_op);
5728
5729         /* Note that the operation could have failed, in that case do
5730            nothing */
5731         if (modest_mail_operation_get_status (mail_op) !=
5732             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5733                 goto frees;
5734
5735         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5736                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5737
5738                 if (!modest_msg_view_window_select_next_message (self) &&
5739                     !modest_msg_view_window_select_previous_message (self)) {
5740                         /* No more messages to view, so close this window */
5741                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5742                 }
5743         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5744                    gtk_tree_row_reference_valid (helper->reference)) {
5745                 GtkWidget *header_view;
5746                 GtkTreePath *path;
5747                 GtkTreeSelection *sel;
5748
5749                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5750                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5751                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5752                 path = gtk_tree_row_reference_get_path (helper->reference);
5753                 /* We need to unselect the previous one
5754                    because we could be copying instead of
5755                    moving */
5756                 gtk_tree_selection_unselect_all (sel);
5757                 gtk_tree_selection_select_path (sel, path);
5758                 gtk_tree_path_free (path);
5759         }
5760         g_object_unref (object);
5761
5762  frees:
5763         /* Destroy the helper */
5764         move_to_helper_destroyer (helper);
5765 }
5766
5767 static void
5768 folder_move_to_cb (ModestMailOperation *mail_op,
5769                    TnyFolder *new_folder,
5770                    gpointer user_data)
5771 {
5772         GtkWidget *folder_view;
5773         GObject *object;
5774
5775         object = modest_mail_operation_get_source (mail_op);
5776         if (MODEST_IS_MAIN_WINDOW (object)) {
5777                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5778                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5779                 g_object_ref (folder_view);
5780                 g_object_unref (object);
5781                 move_to_cb (mail_op, user_data);
5782                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5783                 g_object_unref (folder_view);
5784         } else {
5785                 move_to_cb (mail_op, user_data);
5786         }
5787 }
5788
5789 static void
5790 msgs_move_to_cb (ModestMailOperation *mail_op,
5791                  gpointer user_data)
5792 {
5793         move_to_cb (mail_op, user_data);
5794 }
5795
5796 void
5797 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5798                                              gpointer user_data)
5799 {
5800         GObject *win = NULL;
5801         const GError *error;
5802         TnyAccount *account = NULL;
5803
5804 #ifndef MODEST_TOOLKIT_HILDON2
5805         ModestWindow *main_window = NULL;
5806
5807         /* Disable next automatic folder selection */
5808         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5809                                                          FALSE); /* don't create */
5810
5811         /* Show notification dialog only if the main window exists */
5812         if (main_window) {
5813                 GtkWidget *folder_view = NULL;
5814
5815                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5816                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5817                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5818
5819                 if (user_data && TNY_IS_FOLDER (user_data)) {
5820                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5821                                                           TNY_FOLDER (user_data), FALSE);
5822                 }
5823         }
5824 #endif
5825         win = modest_mail_operation_get_source (mail_op);
5826         error = modest_mail_operation_get_error (mail_op);
5827
5828         if (TNY_IS_FOLDER (user_data))
5829                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5830         else if (TNY_IS_ACCOUNT (user_data))
5831                 account = g_object_ref (user_data);
5832
5833         /* If it's not a disk full error then show a generic error */
5834         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5835                                                              (GtkWidget *) win, (GError *) error,
5836                                                              account, NULL))
5837                 modest_platform_run_information_dialog ((GtkWindow *) win,
5838                                                         _("mail_in_ui_folder_move_target_error"),
5839                                                         FALSE);
5840         if (account)
5841                 g_object_unref (account);
5842         if (win)
5843                 g_object_unref (win);
5844 }
5845
5846 static void
5847 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5848                        TnyHeader *header,
5849                        gboolean canceled,
5850                        TnyMsg *msg,
5851                        GError *err,
5852                        gpointer user_data)
5853 {
5854         TnyList *parts;
5855         TnyIterator *iter;
5856         gint pending_purges = 0;
5857         gboolean some_purged = FALSE;
5858         ModestWindow *win = MODEST_WINDOW (user_data);
5859         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5860
5861         /* If there was any error */
5862         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5863                 modest_window_mgr_unregister_header (mgr, header);
5864                 return;
5865         }
5866
5867         /* Once the message has been retrieved for purging, we check if
5868          * it's all ok for purging */
5869
5870         parts = tny_simple_list_new ();
5871         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5872         iter = tny_list_create_iterator (parts);
5873
5874         while (!tny_iterator_is_done (iter)) {
5875                 TnyMimePart *part;
5876                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5877                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5878                         if (tny_mime_part_is_purged (part))
5879                                 some_purged = TRUE;
5880                         else
5881                                 pending_purges++;
5882                 }
5883
5884                 if (part)
5885                         g_object_unref (part);
5886
5887                 tny_iterator_next (iter);
5888         }
5889         g_object_unref (iter);
5890
5891
5892         if (pending_purges>0) {
5893                 gint response;
5894                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5895
5896                 if (response == GTK_RESPONSE_OK) {
5897                         GtkWidget *info;
5898                         info =
5899                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5900                         iter = tny_list_create_iterator (parts);
5901                         while (!tny_iterator_is_done (iter)) {
5902                                 TnyMimePart *part;
5903
5904                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5905                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5906                                         tny_mime_part_set_purged (part);
5907
5908                                 if (part)
5909                                         g_object_unref (part);
5910
5911                                 tny_iterator_next (iter);
5912                         }
5913                         g_object_unref (iter);
5914
5915                         tny_msg_rewrite_cache (msg);
5916
5917                         gtk_widget_destroy (info);
5918                 }
5919         }
5920
5921         modest_window_mgr_unregister_header (mgr, header);
5922
5923         g_object_unref (parts);
5924 }
5925
5926 static void
5927 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5928                                                      ModestMainWindow *win)
5929 {
5930         GtkWidget *header_view;
5931         TnyList *header_list;
5932         TnyHeader *header;
5933         TnyHeaderFlags flags;
5934         ModestWindow *msg_view_window =  NULL;
5935         gboolean found;
5936
5937         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5938
5939         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5940                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5941
5942         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5943         if (!header_list) {
5944                 g_warning ("%s: no header selected", __FUNCTION__);
5945                 return;
5946         }
5947
5948         if (tny_list_get_length (header_list) == 1) {
5949                 TnyIterator *iter = tny_list_create_iterator (header_list);
5950                 header = TNY_HEADER (tny_iterator_get_current (iter));
5951                 g_object_unref (iter);
5952         } else
5953                 return;
5954
5955         if (!header || !TNY_IS_HEADER(header)) {
5956                 g_warning ("%s: header is not valid", __FUNCTION__);
5957                 return;
5958         }
5959
5960         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5961                                                           header, &msg_view_window);
5962         flags = tny_header_get_flags (header);
5963         if (!(flags & TNY_HEADER_FLAG_CACHED))
5964                 return;
5965         if (found) {
5966                 if (msg_view_window != NULL)
5967                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5968                 else {
5969                         /* do nothing; uid was registered before, so window is probably on it's way */
5970                         g_debug ("header %p has already been registered", header);
5971                 }
5972         } else {
5973                 ModestMailOperation *mail_op = NULL;
5974                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5975                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5976                                                                          modest_ui_actions_disk_operations_error_handler,
5977                                                                          NULL, NULL);
5978                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5979                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5980
5981                 g_object_unref (mail_op);
5982         }
5983         if (header)
5984                 g_object_unref (header);
5985         if (header_list)
5986                 g_object_unref (header_list);
5987 }
5988
5989 /*
5990  * Checks if we need a connection to do the transfer and if the user
5991  * wants to connect to complete it
5992  */
5993 static void
5994 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5995                                        TnyFolderStore *src_folder,
5996                                        TnyList *headers,
5997                                        TnyFolder *dst_folder,
5998                                        gboolean delete_originals,
5999                                        gboolean *need_connection,
6000                                        gboolean *do_xfer)
6001 {
6002         TnyAccount *src_account;
6003         gint uncached_msgs = 0;
6004
6005         /* We don't need any further check if
6006          *
6007          * 1- the source folder is local OR
6008          * 2- the device is already online
6009          */
6010         if (!modest_tny_folder_store_is_remote (src_folder) ||
6011             tny_device_is_online (modest_runtime_get_device())) {
6012                 *need_connection = FALSE;
6013                 *do_xfer = TRUE;
6014                 return;
6015         }
6016
6017         /* We must ask for a connection when
6018          *
6019          *   - the message(s) is not already cached   OR
6020          *   - the message(s) is cached but the leave_on_server setting
6021          * is FALSE (because we need to sync the source folder to
6022          * delete the message from the server (for IMAP we could do it
6023          * offline, it'll take place the next time we get a
6024          * connection)
6025          */
6026         uncached_msgs = header_list_count_uncached_msgs (headers);
6027         src_account = get_account_from_folder_store (src_folder);
6028         if (uncached_msgs > 0) {
6029                 guint num_headers;
6030                 const gchar *msg;
6031
6032                 *need_connection = TRUE;
6033                 num_headers = tny_list_get_length (headers);
6034                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
6035
6036                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
6037                     GTK_RESPONSE_CANCEL) {
6038                         *do_xfer = FALSE;
6039                 } else {
6040                         *do_xfer = TRUE;
6041                 }
6042         } else {
6043                 /* The transfer is possible and the user wants to */
6044                 *do_xfer = TRUE;
6045
6046                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
6047                         const gchar *account_name;
6048                         gboolean leave_on_server;
6049
6050                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
6051                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
6052                                                                                   account_name);
6053
6054                         if (leave_on_server == TRUE) {
6055                                 *need_connection = FALSE;
6056                         } else {
6057                                 *need_connection = TRUE;
6058                         }
6059                 } else {
6060                         *need_connection = FALSE;
6061                 }
6062         }
6063
6064         /* Frees */
6065         g_object_unref (src_account);
6066 }
6067
6068 static void
6069 xfer_messages_error_handler (ModestMailOperation *mail_op,
6070                              gpointer user_data)
6071 {
6072         GObject *win;
6073         const GError *error;
6074         TnyAccount *account;
6075
6076         win = modest_mail_operation_get_source (mail_op);
6077         error = modest_mail_operation_get_error (mail_op);
6078
6079         /* We cannot get the account from the mail op as that is the
6080            source account and for checking memory full conditions we
6081            need the destination one */
6082         account = TNY_ACCOUNT (user_data);
6083
6084         if (error &&
6085             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6086                                                              (GtkWidget *) win, (GError*) error,
6087                                                              account, _KR("cerm_memory_card_full"))) {
6088                 modest_platform_run_information_dialog ((GtkWindow *) win,
6089                                                         _("mail_in_ui_folder_move_target_error"),
6090                                                         FALSE);
6091         }
6092         if (win)
6093                 g_object_unref (win);
6094 }
6095
6096 typedef struct {
6097         TnyFolderStore *dst_folder;
6098         TnyList *headers;
6099 } XferMsgsHelper;
6100
6101 /**
6102  * Utility function that transfer messages from both the main window
6103  * and the msg view window when using the "Move to" dialog
6104  */
6105 static void
6106 xfer_messages_performer  (gboolean canceled,
6107                           GError *err,
6108                           GtkWindow *parent_window,
6109                           TnyAccount *account,
6110                           gpointer user_data)
6111 {
6112         ModestWindow *win = MODEST_WINDOW (parent_window);
6113         TnyAccount *dst_account = NULL;
6114         gboolean dst_forbids_message_add = FALSE;
6115         XferMsgsHelper *helper;
6116         MoveToHelper *movehelper;
6117         ModestMailOperation *mail_op;
6118
6119         helper = (XferMsgsHelper *) user_data;
6120
6121         if (canceled || err) {
6122                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6123                                                                      (GtkWidget *) parent_window, err,
6124                                                                      account, NULL)) {
6125                         /* Show the proper error message */
6126                         modest_ui_actions_on_account_connection_error (parent_window, account);
6127                 }
6128                 goto end;
6129         }
6130
6131         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
6132
6133         /* tinymail will return NULL for local folders it seems */
6134         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
6135                                                                                   modest_tny_account_get_protocol_type (dst_account),
6136                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
6137
6138         if (dst_forbids_message_add) {
6139                 modest_platform_information_banner (GTK_WIDGET (win),
6140                                                     NULL,
6141                                                     ngettext("mail_in_ui_folder_move_target_error",
6142                                                              "mail_in_ui_folder_move_targets_error",
6143                                                              tny_list_get_length (helper->headers)));
6144                 goto end;
6145         }
6146
6147         movehelper = g_new0 (MoveToHelper, 1);
6148
6149 #ifndef MODEST_TOOLKIT_HILDON2
6150         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
6151                                                                _CS("ckct_nw_pasting"));
6152         if (movehelper->banner != NULL)  {
6153                 g_object_ref (movehelper->banner);
6154                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
6155         }
6156 #endif
6157
6158         if (MODEST_IS_MAIN_WINDOW (win)) {
6159                 GtkWidget *header_view =
6160                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6161                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6162                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
6163         }
6164
6165         /* Perform the mail operation */
6166         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
6167                                                                  xfer_messages_error_handler,
6168                                                                  g_object_ref (dst_account),
6169                                                                  g_object_unref);
6170         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
6171                                          mail_op);
6172
6173         modest_mail_operation_xfer_msgs (mail_op,
6174                                          helper->headers,
6175                                          TNY_FOLDER (helper->dst_folder),
6176                                          TRUE,
6177                                          msgs_move_to_cb,
6178                                          movehelper);
6179
6180         g_object_unref (G_OBJECT (mail_op));
6181  end:
6182         if (dst_account)
6183                 g_object_unref (dst_account);
6184         g_object_unref (helper->dst_folder);
6185         g_object_unref (helper->headers);
6186         g_slice_free (XferMsgsHelper, helper);
6187 }
6188
6189 typedef struct {
6190         TnyFolder *src_folder;
6191         TnyFolderStore *dst_folder;
6192         gboolean delete_original;
6193         GtkWidget *folder_view;
6194 } MoveFolderInfo;
6195
6196 static void
6197 on_move_folder_cb (gboolean canceled,
6198                    GError *err,
6199                    GtkWindow *parent_window,
6200                    TnyAccount *account,
6201                    gpointer user_data)
6202 {
6203         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
6204         GtkTreeSelection *sel;
6205         ModestMailOperation *mail_op = NULL;
6206
6207         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
6208                 /* Note that the connection process can fail due to
6209                    memory low conditions as it can not successfully
6210                    store the summary */
6211                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6212                                                                      (GtkWidget*) parent_window, err,
6213                                                                      account, NULL))
6214                         g_debug ("Error connecting when trying to move a folder");
6215
6216                 g_object_unref (G_OBJECT (info->src_folder));
6217                 g_object_unref (G_OBJECT (info->dst_folder));
6218                 g_free (info);
6219                 return;
6220         }
6221
6222         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
6223 #ifndef MODEST_TOOLKIT_HILDON2
6224         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
6225                         _CS("ckct_nw_pasting"));
6226         if (helper->banner != NULL)  {
6227                 g_object_ref (helper->banner);
6228                 gtk_widget_show (GTK_WIDGET(helper->banner));
6229         }
6230 #endif
6231         /* Clean folder on header view before moving it */
6232         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
6233         gtk_tree_selection_unselect_all (sel);
6234
6235         /* Let gtk events run. We need that the folder
6236            view frees its reference to the source
6237            folder *before* issuing the mail operation
6238            so we need the signal handler of selection
6239            changed to happen before the mail
6240            operation
6241         while (gtk_events_pending ())
6242                 gtk_main_iteration ();   */
6243
6244         mail_op =
6245                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
6246                                                                modest_ui_actions_move_folder_error_handler,
6247                                                                g_object_ref (info->dst_folder), g_object_unref);
6248         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
6249                                          mail_op);
6250
6251         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
6252                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
6253                                                   TNY_FOLDER (info->dst_folder), TRUE);
6254         }
6255         modest_mail_operation_xfer_folder (mail_op,
6256                         TNY_FOLDER (info->src_folder),
6257                         info->dst_folder,
6258                         info->delete_original,
6259                         folder_move_to_cb,
6260                         helper);
6261         g_object_unref (G_OBJECT (info->src_folder));
6262
6263         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
6264         /* } */
6265
6266         /* Unref mail operation */
6267         g_object_unref (G_OBJECT (mail_op));
6268         g_object_unref (G_OBJECT (info->dst_folder));
6269         g_free (user_data);
6270 }
6271
6272 static TnyAccount *
6273 get_account_from_folder_store (TnyFolderStore *folder_store)
6274 {
6275         if (TNY_IS_ACCOUNT (folder_store))
6276                 return g_object_ref (folder_store);
6277         else
6278                 return tny_folder_get_account (TNY_FOLDER (folder_store));
6279 }
6280
6281 /*
6282  * UI handler for the "Move to" action when invoked from the
6283  * ModestMainWindow
6284  */
6285 static void
6286 modest_ui_actions_on_main_window_move_to (GtkAction *action,
6287                                           GtkWidget *folder_view,
6288                                           TnyFolderStore *dst_folder,
6289                                           ModestMainWindow *win)
6290 {
6291         ModestHeaderView *header_view = NULL;
6292         TnyFolderStore *src_folder = NULL;
6293
6294         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
6295
6296         /* Get the source folder */
6297         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6298
6299         /* Get header view */
6300         header_view = (ModestHeaderView *)
6301                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6302
6303         /* Get folder or messages to transfer */
6304         if (gtk_widget_is_focus (folder_view)) {
6305                 gboolean do_xfer = TRUE;
6306
6307                 /* Allow only to transfer folders to the local root folder */
6308                 if (TNY_IS_ACCOUNT (dst_folder) &&
6309                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6310                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6311                         do_xfer = FALSE;
6312                 } else if (!TNY_IS_FOLDER (src_folder)) {
6313                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6314                         do_xfer = FALSE;
6315                 }
6316
6317                 if (do_xfer) {
6318                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6319                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6320
6321                         info->src_folder = g_object_ref (src_folder);
6322                         info->dst_folder = g_object_ref (dst_folder);
6323                         info->delete_original = TRUE;
6324                         info->folder_view = folder_view;
6325
6326                         connect_info->callback = on_move_folder_cb;
6327                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6328                         connect_info->data = info;
6329
6330                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6331                                                                    TNY_FOLDER_STORE (src_folder),
6332                                                                    connect_info);
6333                 }
6334         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
6335                 TnyList *headers;
6336
6337                 headers = modest_header_view_get_selected_headers(header_view);
6338
6339                 /* Transfer the messages */
6340                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6341                                                             headers, TNY_FOLDER (dst_folder));
6342
6343                 g_object_unref (headers);
6344         }
6345
6346         /* Frees */
6347         g_object_unref (src_folder);
6348 }
6349
6350 #ifdef MODEST_TOOLKIT_HILDON2
6351 /*
6352  * UI handler for the "Move to" action when invoked from the
6353  * ModestFolderWindow
6354  */
6355 static void
6356 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6357                                             TnyFolderStore *dst_folder,
6358                                             TnyList *selection,
6359                                             GtkWindow *win)
6360 {
6361         TnyFolderStore *src_folder = NULL;
6362         TnyIterator *iterator;
6363
6364         if (tny_list_get_length (selection) != 1)
6365                 return;
6366
6367         iterator = tny_list_create_iterator (selection);
6368         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6369         g_object_unref (iterator);
6370
6371
6372         gboolean do_xfer = TRUE;
6373
6374         /* Allow only to transfer folders to the local root folder */
6375         if (TNY_IS_ACCOUNT (dst_folder) &&
6376             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6377             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6378                 do_xfer = FALSE;
6379                 /* Show an error */
6380                 modest_platform_run_information_dialog (win,
6381                                                         _("mail_in_ui_folder_move_target_error"),
6382                                                         FALSE);
6383         } else if (!TNY_IS_FOLDER (src_folder)) {
6384                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6385                 do_xfer = FALSE;
6386         }
6387
6388         if (do_xfer) {
6389                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6390                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6391
6392                 info->src_folder = g_object_ref (src_folder);
6393                 info->dst_folder = g_object_ref (dst_folder);
6394                 info->delete_original = TRUE;
6395                 info->folder_view = folder_view;
6396
6397                 connect_info->callback = on_move_folder_cb;
6398                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6399                 connect_info->data = info;
6400
6401                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6402                                                            TNY_FOLDER_STORE (src_folder),
6403                                                            connect_info);
6404         }
6405
6406         /* Frees */
6407         g_object_unref (src_folder);
6408 }
6409 #endif
6410
6411
6412 void
6413 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6414                                             TnyFolder *src_folder,
6415                                             TnyList *headers,
6416                                             TnyFolder *dst_folder)
6417 {
6418         gboolean need_connection = TRUE;
6419         gboolean do_xfer = TRUE;
6420         XferMsgsHelper *helper;
6421
6422         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6423         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6424         g_return_if_fail (TNY_IS_LIST (headers));
6425
6426         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6427                                                headers, TNY_FOLDER (dst_folder),
6428                                                TRUE, &need_connection,
6429                                                &do_xfer);
6430
6431         /* If we don't want to transfer just return */
6432         if (!do_xfer)
6433                 return;
6434
6435         /* Create the helper */
6436         helper = g_slice_new (XferMsgsHelper);
6437         helper->dst_folder = g_object_ref (dst_folder);
6438         helper->headers = g_object_ref (headers);
6439
6440         if (need_connection) {
6441                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6442                 connect_info->callback = xfer_messages_performer;
6443                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6444                 connect_info->data = helper;
6445
6446                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6447                                                            TNY_FOLDER_STORE (src_folder),
6448                                                            connect_info);
6449         } else {
6450                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6451                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6452                                          src_account, helper);
6453                 g_object_unref (src_account);
6454         }
6455 }
6456
6457 /*
6458  * UI handler for the "Move to" action when invoked from the
6459  * ModestMsgViewWindow
6460  */
6461 static void
6462 modest_ui_actions_on_window_move_to (GtkAction *action,
6463                                      TnyList *headers,
6464                                      TnyFolderStore *dst_folder,
6465                                      ModestWindow *win)
6466 {
6467         TnyFolder *src_folder = NULL;
6468
6469         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6470
6471         if (headers) {
6472                 TnyHeader *header = NULL;
6473                 TnyIterator *iter;
6474
6475                 iter = tny_list_create_iterator (headers);
6476                 header = (TnyHeader *) tny_iterator_get_current (iter);
6477                 src_folder = tny_header_get_folder (header);
6478
6479                 /* Transfer the messages */
6480                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6481                                                             headers,
6482                                                             TNY_FOLDER (dst_folder));
6483
6484                 /* Frees */
6485                 g_object_unref (header);
6486                 g_object_unref (iter);
6487                 g_object_unref (src_folder);
6488         }
6489 }
6490
6491 void
6492 modest_ui_actions_on_move_to (GtkAction *action,
6493                               ModestWindow *win)
6494 {
6495         modest_ui_actions_on_edit_mode_move_to (win);
6496 }
6497
6498 gboolean
6499 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6500 {
6501         GtkWidget *dialog = NULL;
6502         MoveToInfo *helper = NULL;
6503         TnyList *list_to_move;
6504
6505         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6506
6507 #ifndef MODEST_TOOLKIT_HILDON2
6508         /* Get the main window if exists */
6509         ModestMainWindow *main_window;
6510         if (MODEST_IS_MAIN_WINDOW (win))
6511                 main_window = MODEST_MAIN_WINDOW (win);
6512         else
6513                 main_window =
6514                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6515                                                                                FALSE)); /* don't create */
6516 #endif
6517
6518         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6519
6520         if (!list_to_move)
6521                 return FALSE;
6522
6523         if (tny_list_get_length (list_to_move) < 1) {
6524                 g_object_unref (list_to_move);
6525                 return FALSE;
6526         }
6527
6528         /* Create and run the dialog */
6529         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6530         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6531                                      GTK_WINDOW (dialog),
6532                                      (GtkWindow *) win);
6533
6534         /* Create helper */
6535         helper = g_slice_new0 (MoveToInfo);
6536         helper->list = list_to_move;
6537         helper->win = win;
6538
6539         /* Listen to response signal */
6540         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6541
6542         /* Show the dialog */
6543         gtk_widget_show (dialog);
6544
6545         return FALSE;
6546 }
6547
6548 /*
6549  * Calls #HeadersFunc for each header already selected in the main
6550  * window or the message currently being shown in the msg view window
6551  */
6552 static void
6553 do_headers_action (ModestWindow *win,
6554                    HeadersFunc func,
6555                    gpointer user_data)
6556 {
6557         TnyList *headers_list = NULL;
6558         TnyIterator *iter = NULL;
6559         TnyHeader *header = NULL;
6560         TnyFolder *folder = NULL;
6561
6562         /* Get headers */
6563         headers_list = get_selected_headers (win);
6564         if (!headers_list)
6565                 return;
6566
6567         /* Get the folder */
6568         iter = tny_list_create_iterator (headers_list);
6569         header = TNY_HEADER (tny_iterator_get_current (iter));
6570         if (header) {
6571                 folder = tny_header_get_folder (header);
6572                 g_object_unref (header);
6573         }
6574
6575         /* Call the function for each header */
6576         while (!tny_iterator_is_done (iter)) {
6577                 header = TNY_HEADER (tny_iterator_get_current (iter));
6578                 func (header, win, user_data);
6579                 g_object_unref (header);
6580                 tny_iterator_next (iter);
6581         }
6582
6583         /* Trick: do a poke status in order to speed up the signaling
6584            of observers */
6585         if (folder) {
6586                 tny_folder_poke_status (folder);
6587                 g_object_unref (folder);
6588         }
6589
6590         /* Frees */
6591         g_object_unref (iter);
6592         g_object_unref (headers_list);
6593 }
6594
6595 void
6596 modest_ui_actions_view_attachment (GtkAction *action,
6597                                    ModestWindow *window)
6598 {
6599         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6600                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6601         } else {
6602                 /* not supported window for this action */
6603                 g_return_if_reached ();
6604         }
6605 }
6606
6607 void
6608 modest_ui_actions_save_attachments (GtkAction *action,
6609                                     ModestWindow *window)
6610 {
6611         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6612
6613                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6614                         return;
6615
6616                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6617         } else {
6618                 /* not supported window for this action */
6619                 g_return_if_reached ();
6620         }
6621 }
6622
6623 void
6624 modest_ui_actions_remove_attachments (GtkAction *action,
6625                                       ModestWindow *window)
6626 {
6627         if (MODEST_IS_MAIN_WINDOW (window)) {
6628                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6629         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6630                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6631         } else {
6632                 /* not supported window for this action */
6633                 g_return_if_reached ();
6634         }
6635 }
6636
6637 void
6638 modest_ui_actions_on_settings (GtkAction *action,
6639                                ModestWindow *win)
6640 {
6641         GtkWidget *dialog;
6642
6643         dialog = modest_platform_get_global_settings_dialog ();
6644         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6645         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6646         gtk_widget_show_all (dialog);
6647
6648         gtk_dialog_run (GTK_DIALOG (dialog));
6649
6650         gtk_widget_destroy (dialog);
6651 }
6652
6653 void
6654 modest_ui_actions_on_help (GtkAction *action,
6655                            GtkWindow *win)
6656 {
6657         /* Help app is not available at all in fremantle */
6658 #ifndef MODEST_TOOLKIT_HILDON2
6659         const gchar *help_id;
6660
6661         g_return_if_fail (win && GTK_IS_WINDOW(win));
6662
6663         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6664
6665         if (help_id)
6666                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6667 #endif
6668 }
6669
6670 void
6671 modest_ui_actions_on_csm_help (GtkAction *action,
6672                                GtkWindow *win)
6673 {
6674         /* Help app is not available at all in fremantle */
6675 #ifndef MODEST_TOOLKIT_HILDON2
6676
6677         const gchar* help_id = NULL;
6678         GtkWidget *folder_view;
6679         TnyFolderStore *folder_store;
6680
6681         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6682
6683         /* Get selected folder */
6684         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6685                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6686         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6687
6688         /* Switch help_id */
6689         if (folder_store && TNY_IS_FOLDER (folder_store))
6690                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6691
6692         if (folder_store)
6693                 g_object_unref (folder_store);
6694
6695         if (help_id)
6696                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6697         else
6698                 modest_ui_actions_on_help (action, win);
6699 #endif
6700 }
6701
6702 static void
6703 retrieve_contents_cb (ModestMailOperation *mail_op,
6704                       TnyHeader *header,
6705                       gboolean canceled,
6706                       TnyMsg *msg,
6707                       GError *err,
6708                       gpointer user_data)
6709 {
6710         /* We only need this callback to show an error in case of
6711            memory low condition */
6712         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6713                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6714         }
6715 }
6716
6717 static void
6718 retrieve_msg_contents_performer (gboolean canceled,
6719                                  GError *err,
6720                                  GtkWindow *parent_window,
6721                                  TnyAccount *account,
6722                                  gpointer user_data)
6723 {
6724         ModestMailOperation *mail_op;
6725         TnyList *headers = TNY_LIST (user_data);
6726
6727         if (err || canceled) {
6728                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6729                                                                 (GtkWidget *) parent_window, err,
6730                                                                 account, NULL);
6731                 goto out;
6732         }
6733
6734         /* Create mail operation */
6735         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6736                                                                  modest_ui_actions_disk_operations_error_handler,
6737                                                                  NULL, NULL);
6738         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6739         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6740
6741         /* Frees */
6742         g_object_unref (mail_op);
6743  out:
6744         g_object_unref (headers);
6745         g_object_unref (account);
6746 }
6747
6748 void
6749 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6750                                             ModestWindow *window)
6751 {
6752         TnyList *headers = NULL;
6753         TnyAccount *account = NULL;
6754         TnyIterator *iter = NULL;
6755         TnyHeader *header = NULL;
6756         TnyFolder *folder = NULL;
6757
6758         /* Get headers */
6759         headers = get_selected_headers (window);
6760         if (!headers)
6761                 return;
6762
6763         /* Pick the account */
6764         iter = tny_list_create_iterator (headers);
6765         header = TNY_HEADER (tny_iterator_get_current (iter));
6766         folder = tny_header_get_folder (header);
6767         account = tny_folder_get_account (folder);
6768         g_object_unref (folder);
6769         g_object_unref (header);
6770         g_object_unref (iter);
6771
6772         /* Connect and perform the message retrieval */
6773         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6774                                              g_object_ref (account),
6775                                              retrieve_msg_contents_performer,
6776                                              g_object_ref (headers));
6777
6778         /* Frees */
6779         g_object_unref (account);
6780         g_object_unref (headers);
6781 }
6782
6783 void
6784 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6785 {
6786         g_return_if_fail (MODEST_IS_WINDOW (window));
6787
6788         /* Update dimmed */
6789         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6790 }
6791
6792 void
6793 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6794 {
6795         g_return_if_fail (MODEST_IS_WINDOW (window));
6796
6797         /* Update dimmed */
6798         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6799 }
6800
6801 void
6802 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6803                                           ModestWindow *window)
6804 {
6805         g_return_if_fail (MODEST_IS_WINDOW (window));
6806
6807         /* Update dimmed */
6808         modest_ui_actions_check_menu_dimming_rules (window);
6809 }
6810
6811 void
6812 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6813                                           ModestWindow *window)
6814 {
6815         g_return_if_fail (MODEST_IS_WINDOW (window));
6816
6817         /* Update dimmed */
6818         modest_ui_actions_check_menu_dimming_rules (window);
6819 }
6820
6821 void
6822 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6823                                           ModestWindow *window)
6824 {
6825         g_return_if_fail (MODEST_IS_WINDOW (window));
6826
6827         /* Update dimmed */
6828         modest_ui_actions_check_menu_dimming_rules (window);
6829 }
6830
6831 void
6832 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6833                                             ModestWindow *window)
6834 {
6835         g_return_if_fail (MODEST_IS_WINDOW (window));
6836
6837         /* Update dimmed */
6838         modest_ui_actions_check_menu_dimming_rules (window);
6839 }
6840
6841 void
6842 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6843                                           ModestWindow *window)
6844 {
6845         g_return_if_fail (MODEST_IS_WINDOW (window));
6846
6847         /* Update dimmed */
6848         modest_ui_actions_check_menu_dimming_rules (window);
6849 }
6850
6851 void
6852 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6853                                           ModestWindow *window)
6854 {
6855         g_return_if_fail (MODEST_IS_WINDOW (window));
6856
6857         /* Update dimmed */
6858         modest_ui_actions_check_menu_dimming_rules (window);
6859 }
6860
6861 void
6862 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6863                                                  ModestWindow *window)
6864 {
6865         g_return_if_fail (MODEST_IS_WINDOW (window));
6866
6867         /* Update dimmed */
6868         modest_ui_actions_check_menu_dimming_rules (window);
6869 }
6870
6871 void
6872 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6873                                                      ModestWindow *window)
6874 {
6875         g_return_if_fail (MODEST_IS_WINDOW (window));
6876
6877         /* Update dimmed */
6878         modest_ui_actions_check_menu_dimming_rules (window);
6879 }
6880
6881 void
6882 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6883                                                      ModestWindow *window)
6884 {
6885         g_return_if_fail (MODEST_IS_WINDOW (window));
6886
6887         /* Update dimmed */
6888         modest_ui_actions_check_menu_dimming_rules (window);
6889 }
6890
6891 void
6892 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6893 {
6894         g_return_if_fail (MODEST_IS_WINDOW (window));
6895
6896         /* we check for low-mem; in that case, show a warning, and don't allow
6897          * searching
6898          */
6899         if (modest_platform_check_memory_low (window, TRUE))
6900                 return;
6901
6902         modest_platform_show_search_messages (GTK_WINDOW (window));
6903 }
6904
6905 void
6906 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6907 {
6908         g_return_if_fail (MODEST_IS_WINDOW (win));
6909
6910
6911         /* we check for low-mem; in that case, show a warning, and don't allow
6912          * for the addressbook
6913          */
6914         if (modest_platform_check_memory_low (win, TRUE))
6915                 return;
6916
6917
6918         modest_platform_show_addressbook (GTK_WINDOW (win));
6919 }
6920
6921
6922 void
6923 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6924                                           ModestWindow *window)
6925 {
6926         gboolean active;
6927         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6928
6929         if (GTK_IS_TOGGLE_ACTION (action))
6930                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6931         else
6932                 active = TRUE;
6933
6934         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6935                                                     active);
6936 }
6937
6938 static void
6939 on_send_receive_finished (ModestMailOperation  *mail_op,
6940                            gpointer user_data)
6941 {
6942         GtkWidget *header_view, *folder_view;
6943         TnyFolderStore *folder_store;
6944         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6945
6946         /* Set send/receive operation finished */
6947         modest_main_window_notify_send_receive_completed (main_win);
6948
6949         /* Don't refresh the current folder if there were any errors */
6950         if (modest_mail_operation_get_status (mail_op) !=
6951             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6952                 return;
6953
6954         /* Refresh the current folder if we're viewing a window. We do
6955            this because the user won't be able to see the new mails in
6956            the selected folder after a Send&Receive because it only
6957            performs a poke_status, i.e, only the number of read/unread
6958            messages is updated, but the new headers are not
6959            downloaded */
6960         folder_view = modest_main_window_get_child_widget (main_win,
6961                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6962         if (!folder_view)
6963                 return;
6964
6965         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6966
6967         /* Do not need to refresh INBOX again because the
6968            update_account does it always automatically */
6969         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6970             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6971                 ModestMailOperation *refresh_op;
6972
6973                 header_view = modest_main_window_get_child_widget (main_win,
6974                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6975
6976                 /* We do not need to set the contents style
6977                    because it hasn't changed. We also do not
6978                    need to save the widget status. Just force
6979                    a refresh */
6980                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6981                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6982                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6983                                                       folder_refreshed_cb, main_win);
6984                 g_object_unref (refresh_op);
6985         }
6986
6987         if (folder_store)
6988                 g_object_unref (folder_store);
6989 }
6990
6991
6992 void
6993 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6994                                                 TnyHeader *header,
6995                                                 TnyMsg *msg,
6996                                                 GError *err,
6997                                                 gpointer user_data)
6998 {
6999         const gchar* server_name = NULL;
7000         TnyTransportAccount *transport;
7001         gchar *message = NULL;
7002         ModestProtocol *protocol;
7003
7004         /* Don't show anything if the user cancelled something or the
7005          * send receive request is not interactive. Authentication
7006          * errors are managed by the account store so no need to show
7007          * a dialog here again */
7008         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
7009             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
7010             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
7011                 return;
7012
7013
7014         /* Get the server name. Note that we could be using a
7015            connection specific transport account */
7016         transport = (TnyTransportAccount *)
7017                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
7018         if (transport) {
7019                 ModestTnyAccountStore *acc_store;
7020                 const gchar *acc_name;
7021                 TnyTransportAccount *conn_specific;
7022
7023                 acc_store = modest_runtime_get_account_store();
7024                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
7025                 conn_specific = (TnyTransportAccount *)
7026                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
7027                 if (conn_specific) {
7028                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
7029                         g_object_unref (conn_specific);
7030                 } else {
7031                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
7032                 }
7033                 g_object_unref (transport);
7034         }
7035
7036         /* Get protocol */
7037         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
7038                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
7039                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
7040         if (!protocol) {
7041                 g_warning ("%s: Account with no proto", __FUNCTION__);
7042                 return;
7043         }
7044
7045         /* Show the appropriate message text for the GError: */
7046         switch (err->code) {
7047         case TNY_SERVICE_ERROR_CONNECT:
7048                 message = modest_protocol_get_translation (protocol,
7049                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
7050                                                            server_name);
7051                 break;
7052         case TNY_SERVICE_ERROR_SEND:
7053                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
7054                 break;
7055         case TNY_SERVICE_ERROR_UNAVAILABLE:
7056                 message = modest_protocol_get_translation (protocol,
7057                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
7058                                                            server_name);
7059                 break;
7060         default:
7061                 g_warning ("%s: unexpected ERROR %d",
7062                            __FUNCTION__, err->code);
7063                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
7064                 break;
7065         }
7066
7067         modest_platform_run_information_dialog (NULL, message, FALSE);
7068         g_free (message);
7069 }
7070
7071 void
7072 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
7073                                                 gchar *msg_id,
7074                                                 guint status,
7075                                                 gpointer user_data)
7076 {
7077         ModestWindow *top_window = NULL;
7078         ModestWindowMgr *mgr = NULL;
7079         GtkWidget *header_view = NULL;
7080         TnyFolder *selected_folder = NULL;
7081         TnyFolderType folder_type;
7082
7083         mgr = modest_runtime_get_window_mgr ();
7084         top_window = modest_window_mgr_get_current_top (mgr);
7085
7086         if (!top_window)
7087                 return;
7088
7089 #ifndef MODEST_TOOLKIT_HILDON2
7090         if (MODEST_IS_MAIN_WINDOW (top_window)) {
7091                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
7092                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
7093         }
7094 #else
7095         if (MODEST_IS_HEADER_WINDOW (top_window)) {
7096                 header_view = (GtkWidget *)
7097                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
7098         }
7099 #endif
7100
7101         /* Get selected folder */
7102         if (header_view)
7103                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
7104         if (!selected_folder)
7105                 return;
7106
7107         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
7108 #if GTK_CHECK_VERSION(2, 8, 0)
7109         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
7110         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
7111                 GtkTreeViewColumn *tree_column;
7112
7113                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
7114                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
7115                 if (tree_column)
7116                         gtk_tree_view_column_queue_resize (tree_column);
7117                 }
7118 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
7119         gtk_widget_queue_draw (header_view);
7120 #endif
7121
7122 #ifndef MODEST_TOOLKIT_HILDON2
7123         /* Rerun dimming rules, because the message could become deletable for example */
7124         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
7125                                                  MODEST_DIMMING_RULES_TOOLBAR);
7126         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
7127                                                  MODEST_DIMMING_RULES_MENU);
7128 #endif
7129
7130         /* Free */
7131         g_object_unref (selected_folder);
7132 }
7133
7134 void
7135 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
7136                                                TnyAccount *account)
7137 {
7138         ModestProtocolType protocol_type;
7139         ModestProtocol *protocol;
7140         gchar *error_note = NULL;
7141
7142         protocol_type = modest_tny_account_get_protocol_type (account);
7143         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7144                                                                   protocol_type);
7145
7146         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
7147         if (error_note == NULL) {
7148                 g_warning ("%s: This should not be reached", __FUNCTION__);
7149         } else {
7150                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
7151                 g_free (error_note);
7152         }
7153 }
7154
7155 gchar *
7156 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
7157 {
7158         gchar *msg = NULL;
7159         gchar *subject;
7160         TnyFolderStore *folder = NULL;
7161         TnyAccount *account = NULL;
7162         ModestProtocolType proto;
7163         ModestProtocol *protocol;
7164         TnyHeader *header = NULL;
7165
7166         if (MODEST_IS_MAIN_WINDOW (win)) {
7167                 GtkWidget *header_view;
7168                 TnyList* headers = NULL;
7169                 TnyIterator *iter;
7170                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
7171                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
7172                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
7173                 if (!headers || tny_list_get_length (headers) == 0) {
7174                         if (headers)
7175                                 g_object_unref (headers);
7176                         return NULL;
7177                 }
7178                 iter = tny_list_create_iterator (headers);
7179                 header = TNY_HEADER (tny_iterator_get_current (iter));
7180                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7181                 g_object_unref (iter);
7182                 g_object_unref (headers);
7183 #ifdef MODEST_TOOLKIT_HILDON2
7184         } else if (MODEST_IS_HEADER_WINDOW (win)) {
7185                 GtkWidget *header_view;
7186                 TnyList* headers = NULL;
7187                 TnyIterator *iter;
7188                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
7189                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
7190                 if (!headers || tny_list_get_length (headers) == 0) {
7191                         if (headers)
7192                                 g_object_unref (headers);
7193                         return NULL;
7194                 }
7195                 iter = tny_list_create_iterator (headers);
7196                 header = TNY_HEADER (tny_iterator_get_current (iter));
7197                 if (header) {
7198                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7199                 } else {
7200                         g_warning ("List should contain headers");
7201                 }
7202                 g_object_unref (iter);
7203                 g_object_unref (headers);
7204 #endif
7205         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
7206                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
7207                 if (header)
7208                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7209         }
7210
7211         if (!header || !folder)
7212                 goto frees;
7213
7214         /* Get the account type */
7215         account = tny_folder_get_account (TNY_FOLDER (folder));
7216         proto = modest_tny_account_get_protocol_type (account);
7217         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7218                                                                   proto);
7219
7220         subject = tny_header_dup_subject (header);
7221         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
7222         if (subject)
7223                 g_free (subject);
7224         if (msg == NULL) {
7225                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
7226         }
7227
7228  frees:
7229         /* Frees */
7230         if (account)
7231                 g_object_unref (account);
7232         if (folder)
7233                 g_object_unref (folder);
7234         if (header)
7235                 g_object_unref (header);
7236
7237         return msg;
7238 }
7239
7240 gboolean
7241 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
7242                                      const gchar *account_name,
7243                                      const gchar *account_title)
7244 {
7245         ModestAccountMgr *account_mgr;
7246         gchar *txt = NULL;
7247         gint response;
7248         ModestProtocol *protocol;
7249         gboolean removed = FALSE;
7250
7251         g_return_val_if_fail (account_name, FALSE);
7252         g_return_val_if_fail (account_title, FALSE);
7253
7254         account_mgr = modest_runtime_get_account_mgr();
7255
7256         /* The warning text depends on the account type: */
7257         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7258                                                                   modest_account_mgr_get_store_protocol (account_mgr,
7259                                                                                                          account_name));
7260         txt = modest_protocol_get_translation (protocol,
7261                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
7262                                                account_title);
7263         if (txt == NULL)
7264                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
7265
7266         response = modest_platform_run_confirmation_dialog (parent_window, txt);
7267         g_free (txt);
7268         txt = NULL;
7269
7270         if (response == GTK_RESPONSE_OK) {
7271                 /* Remove account. If it succeeds then it also removes
7272                    the account from the ModestAccountView: */
7273                 gboolean is_default = FALSE;
7274                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
7275                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
7276                         is_default = TRUE;
7277                 g_free (default_account_name);
7278
7279                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
7280                 if (removed) {
7281 #ifdef MODEST_TOOLKIT_HILDON2
7282                         hildon_gtk_window_take_screenshot (parent_window, FALSE);
7283 #endif
7284                         /* Close all email notifications, we cannot
7285                            distinguish if the notification belongs to
7286                            this account or not, so for safety reasons
7287                            we remove them all */
7288                         modest_platform_remove_new_mail_notifications (FALSE, account_name);
7289                 } else {
7290                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
7291                 }
7292         }
7293         return removed;
7294 }
7295
7296 static void
7297 on_fetch_images_performer (gboolean canceled,
7298                            GError *err,
7299                            GtkWindow *parent_window,
7300                            TnyAccount *account,
7301                            gpointer user_data)
7302 {
7303         if (err || canceled) {
7304                 /* Show an unable to retrieve images ??? */
7305                 return;
7306         }
7307
7308         /* Note that the user could have closed the window while connecting */
7309         if (GTK_WIDGET_VISIBLE (parent_window))
7310                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
7311         g_object_unref ((GObject *) user_data);
7312 }
7313
7314 void
7315 modest_ui_actions_on_fetch_images (GtkAction *action,
7316                                    ModestWindow *window)
7317 {
7318         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
7319
7320         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
7321                                              NULL,
7322                                              on_fetch_images_performer, 
7323                                              g_object_ref (window));
7324 }
7325
7326 void
7327 modest_ui_actions_on_reload_message (const gchar *msg_id)
7328 {
7329         ModestWindow *window = NULL;
7330
7331         g_return_if_fail (msg_id && msg_id[0] != '\0');
7332         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7333                                                             msg_id,
7334                                                             &window))
7335                 return;
7336
7337
7338         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7339                 return;
7340
7341         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7342 }
7343
7344 /** Check whether any connections are active, and cancel them if 
7345  * the user wishes.
7346  * Returns TRUE is there was no problem, 
7347  * or if an operation was cancelled so we can continue.
7348  * Returns FALSE if the user chose to cancel his request instead.
7349  */
7350
7351 gboolean
7352 modest_ui_actions_check_for_active_account (ModestWindow *self,
7353                                             const gchar* account_name)
7354 {
7355         ModestTnySendQueue *send_queue;
7356         ModestTnyAccountStore *acc_store;
7357         ModestMailOperationQueue* queue;
7358         TnyConnectionStatus store_conn_status;
7359         TnyAccount *store_account = NULL, *transport_account = NULL;
7360         gboolean retval = TRUE, sending = FALSE;
7361
7362         acc_store = modest_runtime_get_account_store ();
7363         queue = modest_runtime_get_mail_operation_queue ();
7364
7365         store_account = 
7366                 modest_tny_account_store_get_server_account (acc_store,
7367                                                              account_name,
7368                                                              TNY_ACCOUNT_TYPE_STORE);
7369
7370         /* This could happen if the account was deleted before the
7371            call to this function */
7372         if (!store_account)
7373                 return FALSE;
7374
7375         transport_account = 
7376                 modest_tny_account_store_get_server_account (acc_store,
7377                                                              account_name,
7378                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7379
7380         /* This could happen if the account was deleted before the
7381            call to this function */
7382         if (!transport_account) {
7383                 g_object_unref (store_account);
7384                 return FALSE;
7385         }
7386
7387         /* If the transport account was not used yet, then the send
7388            queue could not exist (it's created on demand) */
7389         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7390         if (TNY_IS_SEND_QUEUE (send_queue))
7391                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7392
7393         store_conn_status = tny_account_get_connection_status (store_account);
7394         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7395                 gint response;
7396
7397                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7398                                                                 _("emev_nc_disconnect_account"));
7399                 if (response == GTK_RESPONSE_OK) {
7400                         retval = TRUE;
7401                 } else {
7402                         retval = FALSE;
7403                 }
7404         }
7405
7406         if (retval) {
7407
7408                 /* FIXME: We should only cancel those of this account */
7409                 modest_mail_operation_queue_cancel_all (queue);
7410
7411                 /* Also disconnect the account */
7412                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7413                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7414                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7415                                                       FALSE, NULL, NULL);
7416                 }
7417                 if (sending) {
7418                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7419                                                       FALSE, NULL, NULL);
7420                 }
7421         }
7422                 
7423         /* Frees */
7424         g_object_unref (store_account);
7425         g_object_unref (transport_account);
7426         
7427         return retval;
7428 }