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