f0c9d605d758e695b61a049d6465fda797e17978
[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 ("sfil_ni_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("ckdg_ib_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("sfil_ni_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("ckdg_ib_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("ckdg_ib_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("wdgt_bd_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("mcen_ib_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("ecoc_ib_edwin_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("ckct_nw_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("ckct_nw_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("ckct_nw_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 #ifndef MODEST_TOOLKIT_HILDON2
4086         gtk_window_present (GTK_WINDOW (window));
4087 #endif
4088 }
4089
4090 /*
4091  * Used by modest_ui_actions_on_details to call do_headers_action
4092  */
4093 static void
4094 headers_action_show_details (TnyHeader *header,
4095                              ModestWindow *window,
4096                              gpointer user_data)
4097
4098 {
4099         gboolean async_retrieval;
4100         TnyMsg *msg = NULL;
4101
4102         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4103                 async_retrieval = TRUE;
4104                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4105         } else {
4106                 async_retrieval = FALSE;
4107         }
4108         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4109         if (msg)
4110                 g_object_unref (msg);
4111 }
4112
4113 /*
4114  * Show the header details in a ModestDetailsDialog widget
4115  */
4116 void
4117 modest_ui_actions_on_details (GtkAction *action,
4118                               ModestWindow *win)
4119 {
4120         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4121                 TnyMsg *msg;
4122                 TnyHeader *header;
4123
4124                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4125                 if (!msg)
4126                         return;
4127
4128                 header = tny_msg_get_header (msg);
4129                 if (header) {
4130                         headers_action_show_details (header, win, NULL);
4131                         g_object_unref (header);
4132                 }
4133                 g_object_unref (msg);
4134         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4135                 TnyFolder *folder;
4136                 GtkWidget *header_view;
4137
4138                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4139                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4140                 if (folder) {
4141                         GtkWindow *toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) win);
4142
4143                         modest_platform_run_folder_details_dialog (toplevel, folder);
4144                         g_object_unref (folder);
4145                 }
4146         }
4147 }
4148
4149 void
4150 modest_ui_actions_on_limit_error (GtkAction *action,
4151                                   ModestWindow *win)
4152 {
4153         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4154
4155         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4156
4157 }
4158
4159 void
4160 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4161                                      ModestMsgEditWindow *window)
4162 {
4163         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4164
4165         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4166 }
4167
4168 void
4169 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4170                                       ModestMsgEditWindow *window)
4171 {
4172         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4173
4174         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4175 }
4176
4177
4178 void
4179 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4180                                      ModestWindow *window)
4181 {
4182         gboolean active, fullscreen = FALSE;
4183         ModestWindowMgr *mgr;
4184
4185         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4186
4187         /* Check if we want to toggle the toolbar view in fullscreen
4188            or normal mode */
4189         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4190                      "ViewShowToolbarFullScreen")) {
4191                 fullscreen = TRUE;
4192         }
4193
4194         /* Toggle toolbar */
4195         mgr = modest_runtime_get_window_mgr ();
4196         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4197 }
4198
4199 void
4200 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4201                                            ModestMsgEditWindow *window)
4202 {
4203         modest_msg_edit_window_select_font (window);
4204 }
4205
4206
4207 void
4208 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4209                                                   const gchar *display_name,
4210                                                   GtkWindow *window)
4211 {
4212         /* don't update the display name if it was already set;
4213          * updating the display name apparently is expensive */
4214         const gchar* old_name = gtk_window_get_title (window);
4215
4216         if (display_name == NULL)
4217                 display_name = " ";
4218
4219         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4220                 return; /* don't do anything */
4221
4222         /* This is usually used to change the title of the main window, which
4223          * is the one that holds the folder view. Note that this change can
4224          * happen even when the widget doesn't have the focus. */
4225         gtk_window_set_title (window, display_name);
4226
4227 }
4228
4229 void
4230 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4231 {
4232         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4233         modest_msg_edit_window_select_contacts (window);
4234 }
4235
4236 void
4237 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4238 {
4239         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4240         modest_msg_edit_window_check_names (window, FALSE);
4241 }
4242
4243
4244 static void
4245 on_move_to_dialog_response (GtkDialog *dialog,
4246                             gint       response,
4247                             gpointer   user_data)
4248 {
4249         GtkWidget *parent_win;
4250         MoveToInfo *helper = NULL;
4251         ModestFolderView *folder_view;
4252         gboolean unset_edit_mode = FALSE;
4253
4254         helper = (MoveToInfo *) user_data;
4255
4256         parent_win = (GtkWidget *) helper->win;
4257         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4258                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4259         switch (response) {
4260                 TnyFolderStore *dst_folder;
4261                 TnyFolderStore *selected;
4262
4263         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4264                 selected = modest_folder_view_get_selected (folder_view);
4265                 modest_ui_actions_create_folder ((GtkWindow *) dialog, GTK_WIDGET (folder_view), selected);
4266                 g_object_unref (selected);
4267                 return;
4268         case GTK_RESPONSE_NONE:
4269         case GTK_RESPONSE_CANCEL:
4270         case GTK_RESPONSE_DELETE_EVENT:
4271                 break;
4272         case GTK_RESPONSE_OK:
4273                 dst_folder = modest_folder_view_get_selected (folder_view);
4274
4275                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4276                         /* Clean list to move used for filtering */
4277                         modest_folder_view_set_list_to_move (folder_view, NULL);
4278
4279                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4280                                                                     dst_folder,
4281                                                                     helper->list,
4282                                                                     GTK_WINDOW (parent_win));
4283                 } else {
4284                         /* if the user selected a root folder
4285                            (account) then do not perform any action */
4286                         if (TNY_IS_ACCOUNT (dst_folder)) {
4287                                 g_signal_stop_emission_by_name (dialog, "response");
4288                                 return;
4289                         }
4290
4291                         /* Clean list to move used for filtering */
4292                         modest_folder_view_set_list_to_move (folder_view, NULL);
4293
4294                         /* Moving from headers window in edit mode */
4295                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4296                                                              dst_folder,
4297                                                              MODEST_WINDOW (parent_win));
4298                 }
4299
4300                 if (dst_folder)
4301                         g_object_unref (dst_folder);
4302
4303                 unset_edit_mode = TRUE;
4304                 break;
4305         default:
4306                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4307         }
4308
4309         /* Free the helper and exit */
4310         if (helper->list)
4311                 g_object_unref (helper->list);
4312         if (unset_edit_mode) {
4313 #ifdef MODEST_TOOLKIT_HILDON2
4314                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
4315 #endif
4316         }
4317         g_slice_free (MoveToInfo, helper);
4318         gtk_widget_destroy (GTK_WIDGET (dialog));
4319 }
4320
4321 static GtkWidget*
4322 create_move_to_dialog (GtkWindow *win,
4323                        GtkWidget *folder_view,
4324                        TnyList *list_to_move)
4325 {
4326         GtkWidget *dialog, *tree_view = NULL;
4327
4328         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
4329
4330
4331         /* It could happen that we're trying to move a message from a
4332            window (msg window for example) after the main window was
4333            closed, so we can not just get the model of the folder
4334            view */
4335         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4336                 const gchar *visible_id = NULL;
4337
4338                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4339                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4340                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4341                                                MODEST_FOLDER_VIEW(tree_view));
4342
4343                 visible_id =
4344                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4345
4346                 /* Show the same account than the one that is shown in the main window */
4347                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
4348                                                                              visible_id);
4349         } else {
4350                 const gchar *active_account_name = NULL;
4351                 ModestAccountMgr *mgr = NULL;
4352                 ModestAccountSettings *settings = NULL;
4353                 ModestServerAccountSettings *store_settings = NULL;
4354
4355                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4356                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4357                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
4358                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
4359
4360                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4361                 mgr = modest_runtime_get_account_mgr ();
4362                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4363
4364                 if (settings) {
4365                         const gchar *store_account_name;
4366                         store_settings = modest_account_settings_get_store_settings (settings);
4367                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4368
4369                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
4370                                                                                      store_account_name);
4371                         g_object_unref (store_settings);
4372                         g_object_unref (settings);
4373                 }
4374         }
4375
4376         /* we keep a pointer to the embedded folder view, so we can
4377          *   retrieve it with get_folder_view_from_move_to_dialog (see
4378          *   above) later (needed for focus handling)
4379          */
4380         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
4381
4382         /* Hide special folders */
4383         if (list_to_move)
4384                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
4385
4386         gtk_widget_show (GTK_WIDGET (tree_view));
4387
4388         return dialog;
4389 }
4390
4391 /*
4392  * Shows a confirmation dialog to the user when we're moving messages
4393  * from a remote server to the local storage. Returns the dialog
4394  * response. If it's other kind of movement then it always returns
4395  * GTK_RESPONSE_OK
4396  *
4397  * This one is used by the next functions:
4398  *      modest_ui_actions_on_paste                      - commented out
4399  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4400  */
4401 gint
4402 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4403                                              TnyFolder *dest_folder,
4404                                              gboolean delete,
4405                                              TnyList *headers)
4406 {
4407         gint response = GTK_RESPONSE_OK;
4408         TnyAccount *account = NULL;
4409         TnyFolder *src_folder = NULL;
4410         TnyIterator *iter = NULL;
4411         TnyHeader *header = NULL;
4412
4413         /* return with OK if the destination is a remote folder */
4414         if (modest_tny_folder_is_remote_folder (dest_folder))
4415                 return GTK_RESPONSE_OK;
4416
4417         /* Get source folder */
4418         iter = tny_list_create_iterator (headers);
4419         header = TNY_HEADER (tny_iterator_get_current (iter));
4420         if (header) {
4421                 src_folder = tny_header_get_folder (header);
4422                 g_object_unref (header);
4423         }
4424         g_object_unref (iter);
4425
4426         /* if no src_folder, message may be an attahcment */
4427         if (src_folder == NULL)
4428                 return GTK_RESPONSE_CANCEL;
4429
4430         /* If the source is a local or MMC folder */
4431         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4432                 g_object_unref (src_folder);
4433                 return GTK_RESPONSE_OK;
4434         }
4435
4436         /* Get the account */
4437         account = tny_folder_get_account (src_folder);
4438
4439         /* now if offline we ask the user */
4440         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4441                 response = GTK_RESPONSE_OK;
4442         else
4443                 response = GTK_RESPONSE_CANCEL;
4444
4445         /* Frees */
4446         g_object_unref (src_folder);
4447         g_object_unref (account);
4448
4449         return response;
4450 }
4451
4452 static void
4453 move_to_helper_destroyer (gpointer user_data)
4454 {
4455         MoveToHelper *helper = (MoveToHelper *) user_data;
4456
4457         /* Close the "Pasting" information banner */
4458         if (helper->banner) {
4459                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4460                 g_object_unref (helper->banner);
4461         }
4462         if (gtk_tree_row_reference_valid (helper->reference)) {
4463                 gtk_tree_row_reference_free (helper->reference);
4464                 helper->reference = NULL;
4465         }
4466         g_free (helper);
4467 }
4468
4469 static void
4470 move_to_cb (ModestMailOperation *mail_op,
4471             gpointer user_data)
4472 {
4473         MoveToHelper *helper = (MoveToHelper *) user_data;
4474         GObject *object = modest_mail_operation_get_source (mail_op);
4475
4476         /* Note that the operation could have failed, in that case do
4477            nothing */
4478         if (modest_mail_operation_get_status (mail_op) !=
4479             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4480                 goto frees;
4481
4482         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4483                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4484
4485                 if (!modest_msg_view_window_select_next_message (self) &&
4486                     !modest_msg_view_window_select_previous_message (self)) {
4487                         /* No more messages to view, so close this window */
4488                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4489                 }
4490         }
4491         g_object_unref (object);
4492
4493  frees:
4494         /* Destroy the helper */
4495         move_to_helper_destroyer (helper);
4496 }
4497
4498 static void
4499 folder_move_to_cb (ModestMailOperation *mail_op,
4500                    TnyFolder *new_folder,
4501                    gpointer user_data)
4502 {
4503         GObject *object;
4504
4505         object = modest_mail_operation_get_source (mail_op);
4506         {
4507                 move_to_cb (mail_op, user_data);
4508         }
4509 }
4510
4511 static void
4512 msgs_move_to_cb (ModestMailOperation *mail_op,
4513                  gpointer user_data)
4514 {
4515         move_to_cb (mail_op, user_data);
4516 }
4517
4518 void
4519 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4520                                              gpointer user_data)
4521 {
4522         GObject *win = NULL;
4523         const GError *error;
4524         TnyAccount *account = NULL;
4525
4526         win = modest_mail_operation_get_source (mail_op);
4527         error = modest_mail_operation_get_error (mail_op);
4528
4529         if (TNY_IS_FOLDER (user_data))
4530                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
4531         else if (TNY_IS_ACCOUNT (user_data))
4532                 account = g_object_ref (user_data);
4533
4534         /* If it's not a disk full error then show a generic error */
4535         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4536                                                              (GtkWidget *) win, (GError *) error,
4537                                                              account, NULL))
4538                 modest_platform_run_information_dialog ((GtkWindow *) win,
4539                                                         _("mail_in_ui_folder_move_target_error"),
4540                                                         FALSE);
4541         if (account)
4542                 g_object_unref (account);
4543         if (win)
4544                 g_object_unref (win);
4545 }
4546
4547
4548 /*
4549  * Checks if we need a connection to do the transfer and if the user
4550  * wants to connect to complete it
4551  */
4552 static void
4553 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4554                                        TnyFolderStore *src_folder,
4555                                        TnyList *headers,
4556                                        TnyFolder *dst_folder,
4557                                        gboolean delete_originals,
4558                                        gboolean *need_connection,
4559                                        gboolean *do_xfer)
4560 {
4561         TnyAccount *src_account;
4562         gint uncached_msgs = 0;
4563
4564         /* We don't need any further check if
4565          *
4566          * 1- the source folder is local OR
4567          * 2- the device is already online
4568          */
4569         if (!modest_tny_folder_store_is_remote (src_folder) ||
4570             tny_device_is_online (modest_runtime_get_device())) {
4571                 *need_connection = FALSE;
4572                 *do_xfer = TRUE;
4573                 return;
4574         }
4575
4576         /* We must ask for a connection when
4577          *
4578          *   - the message(s) is not already cached   OR
4579          *   - the message(s) is cached but the leave_on_server setting
4580          * is FALSE (because we need to sync the source folder to
4581          * delete the message from the server (for IMAP we could do it
4582          * offline, it'll take place the next time we get a
4583          * connection)
4584          */
4585         uncached_msgs = header_list_count_uncached_msgs (headers);
4586         src_account = get_account_from_folder_store (src_folder);
4587         if (uncached_msgs > 0) {
4588                 guint num_headers;
4589                 const gchar *msg;
4590
4591                 *need_connection = TRUE;
4592                 num_headers = tny_list_get_length (headers);
4593                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4594
4595                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4596                     GTK_RESPONSE_CANCEL) {
4597                         *do_xfer = FALSE;
4598                 } else {
4599                         *do_xfer = TRUE;
4600                 }
4601         } else {
4602                 /* The transfer is possible and the user wants to */
4603                 *do_xfer = TRUE;
4604
4605                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
4606                         const gchar *account_name;
4607                         gboolean leave_on_server;
4608
4609                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4610                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4611                                                                                   account_name);
4612
4613                         if (leave_on_server == TRUE) {
4614                                 *need_connection = FALSE;
4615                         } else {
4616                                 *need_connection = TRUE;
4617                         }
4618                 } else {
4619                         *need_connection = FALSE;
4620                 }
4621         }
4622
4623         /* Frees */
4624         g_object_unref (src_account);
4625 }
4626
4627 static void
4628 xfer_messages_error_handler (ModestMailOperation *mail_op,
4629                              gpointer user_data)
4630 {
4631         GObject *win;
4632         const GError *error;
4633         TnyAccount *account;
4634
4635         win = modest_mail_operation_get_source (mail_op);
4636         error = modest_mail_operation_get_error (mail_op);
4637
4638         /* We cannot get the account from the mail op as that is the
4639            source account and for checking memory full conditions we
4640            need the destination one */
4641         account = TNY_ACCOUNT (user_data);
4642
4643         if (error &&
4644             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4645                                                              (GtkWidget *) win, (GError*) error,
4646                                                              account, _KR("cerm_memory_card_full"))) {
4647                 modest_platform_run_information_dialog ((GtkWindow *) win,
4648                                                         _("mail_in_ui_folder_move_target_error"),
4649                                                         FALSE);
4650         }
4651         if (win)
4652                 g_object_unref (win);
4653 }
4654
4655 typedef struct {
4656         TnyFolderStore *dst_folder;
4657         TnyList *headers;
4658 } XferMsgsHelper;
4659
4660 /**
4661  * Utility function that transfer messages from both the main window
4662  * and the msg view window when using the "Move to" dialog
4663  */
4664 static void
4665 xfer_messages_performer  (gboolean canceled,
4666                           GError *err,
4667                           GtkWindow *parent_window,
4668                           TnyAccount *account,
4669                           gpointer user_data)
4670 {
4671         ModestWindow *win = MODEST_WINDOW (parent_window);
4672         TnyAccount *dst_account = NULL;
4673         gboolean dst_forbids_message_add = FALSE;
4674         XferMsgsHelper *helper;
4675         MoveToHelper *movehelper;
4676         ModestMailOperation *mail_op;
4677
4678         helper = (XferMsgsHelper *) user_data;
4679
4680         if (canceled || err) {
4681                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4682                                                                      (GtkWidget *) parent_window, err,
4683                                                                      account, NULL)) {
4684                         /* Show the proper error message */
4685                         modest_ui_actions_on_account_connection_error (parent_window, account);
4686                 }
4687                 goto end;
4688         }
4689
4690         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
4691
4692         /* tinymail will return NULL for local folders it seems */
4693         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4694                                                                                   modest_tny_account_get_protocol_type (dst_account),
4695                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
4696
4697         if (dst_forbids_message_add) {
4698                 modest_platform_information_banner (GTK_WIDGET (win),
4699                                                     NULL,
4700                                                     ngettext("mail_in_ui_folder_move_target_error",
4701                                                              "mail_in_ui_folder_move_targets_error",
4702                                                              tny_list_get_length (helper->headers)));
4703                 goto end;
4704         }
4705
4706         movehelper = g_new0 (MoveToHelper, 1);
4707
4708
4709         /* Perform the mail operation */
4710         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4711                                                                  xfer_messages_error_handler,
4712                                                                  g_object_ref (dst_account),
4713                                                                  g_object_unref);
4714         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4715                                          mail_op);
4716
4717         modest_mail_operation_xfer_msgs (mail_op,
4718                                          helper->headers,
4719                                          TNY_FOLDER (helper->dst_folder),
4720                                          TRUE,
4721                                          msgs_move_to_cb,
4722                                          movehelper);
4723
4724         g_object_unref (G_OBJECT (mail_op));
4725  end:
4726         if (dst_account)
4727                 g_object_unref (dst_account);
4728         g_object_unref (helper->dst_folder);
4729         g_object_unref (helper->headers);
4730         g_slice_free (XferMsgsHelper, helper);
4731 }
4732
4733 typedef struct {
4734         TnyFolder *src_folder;
4735         TnyFolderStore *dst_folder;
4736         gboolean delete_original;
4737         GtkWidget *folder_view;
4738 } MoveFolderInfo;
4739
4740 static void
4741 on_move_folder_cb (gboolean canceled,
4742                    GError *err,
4743                    GtkWindow *parent_window,
4744                    TnyAccount *account,
4745                    gpointer user_data)
4746 {
4747         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4748         GtkTreeSelection *sel;
4749         ModestMailOperation *mail_op = NULL;
4750
4751         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
4752                 /* Note that the connection process can fail due to
4753                    memory low conditions as it can not successfully
4754                    store the summary */
4755                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4756                                                                      (GtkWidget*) parent_window, err,
4757                                                                      account, NULL))
4758                         g_debug ("Error connecting when trying to move a folder");
4759
4760                 g_object_unref (G_OBJECT (info->src_folder));
4761                 g_object_unref (G_OBJECT (info->dst_folder));
4762                 g_free (info);
4763                 return;
4764         }
4765
4766         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4767 #ifndef MODEST_TOOLKIT_HILDON2
4768         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4769                         _CS("ckct_nw_pasting"));
4770         if (helper->banner != NULL)  {
4771                 g_object_ref (helper->banner);
4772                 gtk_widget_show (GTK_WIDGET(helper->banner));
4773         }
4774 #endif
4775         /* Clean folder on header view before moving it */
4776         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4777         gtk_tree_selection_unselect_all (sel);
4778
4779         /* Let gtk events run. We need that the folder
4780            view frees its reference to the source
4781            folder *before* issuing the mail operation
4782            so we need the signal handler of selection
4783            changed to happen before the mail
4784            operation
4785         while (gtk_events_pending ())
4786                 gtk_main_iteration ();   */
4787
4788         mail_op =
4789                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4790                                                                modest_ui_actions_move_folder_error_handler,
4791                                                                g_object_ref (info->dst_folder), g_object_unref);
4792         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4793                                          mail_op);
4794
4795         modest_mail_operation_xfer_folder (mail_op,
4796                         TNY_FOLDER (info->src_folder),
4797                         info->dst_folder,
4798                         info->delete_original,
4799                         folder_move_to_cb,
4800                         helper);
4801         g_object_unref (G_OBJECT (info->src_folder));
4802
4803         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
4804         /* } */
4805
4806         /* Unref mail operation */
4807         g_object_unref (G_OBJECT (mail_op));
4808         g_object_unref (G_OBJECT (info->dst_folder));
4809         g_free (user_data);
4810 }
4811
4812 static TnyAccount *
4813 get_account_from_folder_store (TnyFolderStore *folder_store)
4814 {
4815         if (TNY_IS_ACCOUNT (folder_store))
4816                 return g_object_ref (folder_store);
4817         else
4818                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4819 }
4820
4821 /*
4822  * UI handler for the "Move to" action when invoked from the
4823  * ModestFolderWindow
4824  */
4825 static void
4826 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
4827                                             TnyFolderStore *dst_folder,
4828                                             TnyList *selection,
4829                                             GtkWindow *win)
4830 {
4831         TnyFolderStore *src_folder = NULL;
4832         TnyIterator *iterator;
4833
4834         if (tny_list_get_length (selection) != 1)
4835                 return;
4836
4837         iterator = tny_list_create_iterator (selection);
4838         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
4839         g_object_unref (iterator);
4840
4841
4842         gboolean do_xfer = TRUE;
4843
4844         /* Allow only to transfer folders to the local root folder */
4845         if (TNY_IS_ACCOUNT (dst_folder) &&
4846             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4847             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4848                 do_xfer = FALSE;
4849                 /* Show an error */
4850                 modest_platform_run_information_dialog (win,
4851                                                         _("mail_in_ui_folder_move_target_error"),
4852                                                         FALSE);
4853         } else if (!TNY_IS_FOLDER (src_folder)) {
4854                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4855                 do_xfer = FALSE;
4856         }
4857
4858         if (do_xfer) {
4859                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4860                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4861
4862                 info->src_folder = g_object_ref (src_folder);
4863                 info->dst_folder = g_object_ref (dst_folder);
4864                 info->delete_original = TRUE;
4865                 info->folder_view = folder_view;
4866
4867                 connect_info->callback = on_move_folder_cb;
4868                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4869                 connect_info->data = info;
4870
4871                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4872                                                            TNY_FOLDER_STORE (src_folder),
4873                                                            connect_info);
4874         }
4875
4876         /* Frees */
4877         g_object_unref (src_folder);
4878 }
4879
4880
4881 void
4882 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
4883                                             TnyFolder *src_folder,
4884                                             TnyList *headers,
4885                                             TnyFolder *dst_folder)
4886 {
4887         gboolean need_connection = TRUE;
4888         gboolean do_xfer = TRUE;
4889         XferMsgsHelper *helper;
4890
4891         g_return_if_fail (TNY_IS_FOLDER (src_folder));
4892         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
4893         g_return_if_fail (TNY_IS_LIST (headers));
4894
4895         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
4896                                                headers, TNY_FOLDER (dst_folder),
4897                                                TRUE, &need_connection,
4898                                                &do_xfer);
4899
4900         /* If we don't want to transfer just return */
4901         if (!do_xfer)
4902                 return;
4903
4904         /* Create the helper */
4905         helper = g_slice_new (XferMsgsHelper);
4906         helper->dst_folder = g_object_ref (dst_folder);
4907         helper->headers = g_object_ref (headers);
4908
4909         if (need_connection) {
4910                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4911                 connect_info->callback = xfer_messages_performer;
4912                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4913                 connect_info->data = helper;
4914
4915                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4916                                                            TNY_FOLDER_STORE (src_folder),
4917                                                            connect_info);
4918         } else {
4919                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
4920                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
4921                                          src_account, helper);
4922                 g_object_unref (src_account);
4923         }
4924 }
4925
4926 /*
4927  * UI handler for the "Move to" action when invoked from the
4928  * ModestMsgViewWindow
4929  */
4930 static void
4931 modest_ui_actions_on_window_move_to (GtkAction *action,
4932                                      TnyList *headers,
4933                                      TnyFolderStore *dst_folder,
4934                                      ModestWindow *win)
4935 {
4936         TnyFolder *src_folder = NULL;
4937
4938         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
4939
4940         if (headers) {
4941                 TnyHeader *header = NULL;
4942                 TnyIterator *iter;
4943
4944                 iter = tny_list_create_iterator (headers);
4945                 header = (TnyHeader *) tny_iterator_get_current (iter);
4946                 src_folder = tny_header_get_folder (header);
4947
4948                 /* Transfer the messages */
4949                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
4950                                                             headers,
4951                                                             TNY_FOLDER (dst_folder));
4952
4953                 /* Frees */
4954                 g_object_unref (header);
4955                 g_object_unref (iter);
4956                 g_object_unref (src_folder);
4957         }
4958 }
4959
4960 void
4961 modest_ui_actions_on_move_to (GtkAction *action,
4962                               ModestWindow *win)
4963 {
4964         modest_ui_actions_on_edit_mode_move_to (win);
4965 }
4966
4967 gboolean
4968 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
4969 {
4970         GtkWidget *dialog = NULL;
4971         MoveToInfo *helper = NULL;
4972         TnyList *list_to_move;
4973
4974         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
4975
4976
4977         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
4978
4979         if (!list_to_move)
4980                 return FALSE;
4981
4982         if (tny_list_get_length (list_to_move) < 1) {
4983                 g_object_unref (list_to_move);
4984                 return FALSE;
4985         }
4986
4987         /* Create and run the dialog */
4988         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
4989         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4990                                      GTK_WINDOW (dialog),
4991                                      (GtkWindow *) win);
4992
4993         /* Create helper */
4994         helper = g_slice_new0 (MoveToInfo);
4995         helper->list = list_to_move;
4996         helper->win = win;
4997
4998         /* Listen to response signal */
4999         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5000
5001         /* Show the dialog */
5002         gtk_widget_show (dialog);
5003
5004         return FALSE;
5005 }
5006
5007 /*
5008  * Calls #HeadersFunc for each header already selected in the main
5009  * window or the message currently being shown in the msg view window
5010  */
5011 static void
5012 do_headers_action (ModestWindow *win,
5013                    HeadersFunc func,
5014                    gpointer user_data)
5015 {
5016         TnyList *headers_list = NULL;
5017         TnyIterator *iter = NULL;
5018         TnyHeader *header = NULL;
5019         TnyFolder *folder = NULL;
5020
5021         /* Get headers */
5022         headers_list = get_selected_headers (win);
5023         if (!headers_list)
5024                 return;
5025
5026         /* Get the folder */
5027         iter = tny_list_create_iterator (headers_list);
5028         header = TNY_HEADER (tny_iterator_get_current (iter));
5029         if (header) {
5030                 folder = tny_header_get_folder (header);
5031                 g_object_unref (header);
5032         }
5033
5034         /* Call the function for each header */
5035         while (!tny_iterator_is_done (iter)) {
5036                 header = TNY_HEADER (tny_iterator_get_current (iter));
5037                 func (header, win, user_data);
5038                 g_object_unref (header);
5039                 tny_iterator_next (iter);
5040         }
5041
5042         /* Trick: do a poke status in order to speed up the signaling
5043            of observers */
5044         if (folder) {
5045                 tny_folder_poke_status (folder);
5046                 g_object_unref (folder);
5047         }
5048
5049         /* Frees */
5050         g_object_unref (iter);
5051         g_object_unref (headers_list);
5052 }
5053
5054 void
5055 modest_ui_actions_view_attachment (GtkAction *action,
5056                                    ModestWindow *window)
5057 {
5058         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5059                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5060         } else {
5061                 /* not supported window for this action */
5062                 g_return_if_reached ();
5063         }
5064 }
5065
5066 void
5067 modest_ui_actions_save_attachments (GtkAction *action,
5068                                     ModestWindow *window)
5069 {
5070         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5071
5072                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5073                         return;
5074
5075                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5076         } else {
5077                 /* not supported window for this action */
5078                 g_return_if_reached ();
5079         }
5080 }
5081
5082 void
5083 modest_ui_actions_remove_attachments (GtkAction *action,
5084                                       ModestWindow *window)
5085 {
5086         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5087                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5088         } else {
5089                 /* not supported window for this action */
5090                 g_return_if_reached ();
5091         }
5092 }
5093
5094 void
5095 modest_ui_actions_on_settings (GtkAction *action,
5096                                ModestWindow *win)
5097 {
5098         GtkWidget *dialog;
5099         GtkWindow *toplevel;
5100
5101         dialog = modest_platform_get_global_settings_dialog ();
5102         toplevel = (GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (win));
5103         gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel);
5104         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5105         gtk_widget_show_all (dialog);
5106
5107         gtk_dialog_run (GTK_DIALOG (dialog));
5108
5109         gtk_widget_destroy (dialog);
5110 }
5111
5112 void
5113 modest_ui_actions_on_help (GtkAction *action,
5114                            GtkWindow *win)
5115 {
5116         /* Help app is not available at all in fremantle */
5117 #ifndef MODEST_TOOLKIT_HILDON2
5118         const gchar *help_id;
5119
5120         g_return_if_fail (win && GTK_IS_WINDOW(win));
5121
5122         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5123
5124         if (help_id)
5125                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5126 #endif
5127 }
5128
5129 void
5130 modest_ui_actions_on_csm_help (GtkAction *action,
5131                                GtkWindow *win)
5132 {
5133         /* Help app is not available at all in fremantle */
5134 }
5135
5136 static void
5137 retrieve_contents_cb (ModestMailOperation *mail_op,
5138                       TnyHeader *header,
5139                       gboolean canceled,
5140                       TnyMsg *msg,
5141                       GError *err,
5142                       gpointer user_data)
5143 {
5144         /* We only need this callback to show an error in case of
5145            memory low condition */
5146         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5147                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
5148         }
5149 }
5150
5151 static void
5152 retrieve_msg_contents_performer (gboolean canceled,
5153                                  GError *err,
5154                                  GtkWindow *parent_window,
5155                                  TnyAccount *account,
5156                                  gpointer user_data)
5157 {
5158         ModestMailOperation *mail_op;
5159         TnyList *headers = TNY_LIST (user_data);
5160
5161         if (err || canceled) {
5162                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5163                                                                 (GtkWidget *) parent_window, err,
5164                                                                 account, NULL);
5165                 goto out;
5166         }
5167
5168         /* Create mail operation */
5169         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5170                                                                  modest_ui_actions_disk_operations_error_handler,
5171                                                                  NULL, NULL);
5172         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5173         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5174
5175         /* Frees */
5176         g_object_unref (mail_op);
5177  out:
5178         g_object_unref (headers);
5179         g_object_unref (account);
5180 }
5181
5182 void
5183 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5184                                             ModestWindow *window)
5185 {
5186         TnyList *headers = NULL;
5187         TnyAccount *account = NULL;
5188         TnyIterator *iter = NULL;
5189         TnyHeader *header = NULL;
5190         TnyFolder *folder = NULL;
5191
5192         /* Get headers */
5193         headers = get_selected_headers (window);
5194         if (!headers)
5195                 return;
5196
5197         /* Pick the account */
5198         iter = tny_list_create_iterator (headers);
5199         header = TNY_HEADER (tny_iterator_get_current (iter));
5200         folder = tny_header_get_folder (header);
5201         account = tny_folder_get_account (folder);
5202         g_object_unref (folder);
5203         g_object_unref (header);
5204         g_object_unref (iter);
5205
5206         /* Connect and perform the message retrieval */
5207         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5208                                              g_object_ref (account),
5209                                              retrieve_msg_contents_performer,
5210                                              g_object_ref (headers));
5211
5212         /* Frees */
5213         g_object_unref (account);
5214         g_object_unref (headers);
5215 }
5216
5217 void
5218 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5219 {
5220         g_return_if_fail (MODEST_IS_WINDOW (window));
5221
5222         /* Update dimmed */
5223         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5224 }
5225
5226 void
5227 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5228 {
5229         g_return_if_fail (MODEST_IS_WINDOW (window));
5230
5231         /* Update dimmed */
5232         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5233 }
5234
5235 void
5236 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5237                                           ModestWindow *window)
5238 {
5239         g_return_if_fail (MODEST_IS_WINDOW (window));
5240
5241         /* Update dimmed */
5242         modest_ui_actions_check_menu_dimming_rules (window);
5243 }
5244
5245 void
5246 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5247                                           ModestWindow *window)
5248 {
5249         g_return_if_fail (MODEST_IS_WINDOW (window));
5250
5251         /* Update dimmed */
5252         modest_ui_actions_check_menu_dimming_rules (window);
5253 }
5254
5255 void
5256 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5257                                           ModestWindow *window)
5258 {
5259         g_return_if_fail (MODEST_IS_WINDOW (window));
5260
5261         /* Update dimmed */
5262         modest_ui_actions_check_menu_dimming_rules (window);
5263 }
5264
5265 void
5266 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5267                                             ModestWindow *window)
5268 {
5269         g_return_if_fail (MODEST_IS_WINDOW (window));
5270
5271         /* Update dimmed */
5272         modest_ui_actions_check_menu_dimming_rules (window);
5273 }
5274
5275 void
5276 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5277                                           ModestWindow *window)
5278 {
5279         g_return_if_fail (MODEST_IS_WINDOW (window));
5280
5281         /* Update dimmed */
5282         modest_ui_actions_check_menu_dimming_rules (window);
5283 }
5284
5285 void
5286 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5287                                           ModestWindow *window)
5288 {
5289         g_return_if_fail (MODEST_IS_WINDOW (window));
5290
5291         /* Update dimmed */
5292         modest_ui_actions_check_menu_dimming_rules (window);
5293 }
5294
5295 void
5296 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5297                                                  ModestWindow *window)
5298 {
5299         g_return_if_fail (MODEST_IS_WINDOW (window));
5300
5301         /* Update dimmed */
5302         modest_ui_actions_check_menu_dimming_rules (window);
5303 }
5304
5305 void
5306 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5307                                                      ModestWindow *window)
5308 {
5309         g_return_if_fail (MODEST_IS_WINDOW (window));
5310
5311         /* Update dimmed */
5312         modest_ui_actions_check_menu_dimming_rules (window);
5313 }
5314
5315 void
5316 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5317                                                      ModestWindow *window)
5318 {
5319         g_return_if_fail (MODEST_IS_WINDOW (window));
5320
5321         /* Update dimmed */
5322         modest_ui_actions_check_menu_dimming_rules (window);
5323 }
5324
5325 void
5326 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5327 {
5328         g_return_if_fail (MODEST_IS_WINDOW (window));
5329
5330         /* we check for low-mem; in that case, show a warning, and don't allow
5331          * searching
5332          */
5333         if (modest_platform_check_memory_low (window, TRUE))
5334                 return;
5335
5336         modest_platform_show_search_messages (GTK_WINDOW (window));
5337 }
5338
5339 void
5340 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5341 {
5342         g_return_if_fail (MODEST_IS_WINDOW (win));
5343
5344
5345         /* we check for low-mem; in that case, show a warning, and don't allow
5346          * for the addressbook
5347          */
5348         if (modest_platform_check_memory_low (win, TRUE))
5349                 return;
5350
5351
5352         modest_platform_show_addressbook (GTK_WINDOW (win));
5353 }
5354
5355
5356 void
5357 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
5358                                           ModestWindow *window)
5359 {
5360         gboolean active;
5361         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5362
5363         if (GTK_IS_TOGGLE_ACTION (action))
5364                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
5365         else
5366                 active = TRUE;
5367
5368         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
5369                                                        active);
5370 }
5371
5372
5373 void
5374 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5375                                                 TnyHeader *header,
5376                                                 TnyMsg *msg,
5377                                                 GError *err,
5378                                                 gpointer user_data)
5379 {
5380         const gchar* server_name = NULL;
5381         TnyTransportAccount *transport;
5382         gchar *message = NULL;
5383         ModestProtocol *protocol;
5384
5385         /* Don't show anything if the user cancelled something or the
5386          * send receive request is not interactive. Authentication
5387          * errors are managed by the account store so no need to show
5388          * a dialog here again */
5389         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5390             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
5391             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5392                 return;
5393
5394
5395         /* Get the server name. Note that we could be using a
5396            connection specific transport account */
5397         transport = (TnyTransportAccount *)
5398                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
5399         if (transport) {
5400                 ModestTnyAccountStore *acc_store;
5401                 const gchar *acc_name;
5402                 TnyTransportAccount *conn_specific;
5403
5404                 acc_store = modest_runtime_get_account_store();
5405                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
5406                 conn_specific = (TnyTransportAccount *)
5407                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
5408                 if (conn_specific) {
5409                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
5410                         g_object_unref (conn_specific);
5411                 } else {
5412                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
5413                 }
5414                 g_object_unref (transport);
5415         }
5416
5417         /* Get protocol */
5418         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
5419                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
5420                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
5421         if (!protocol) {
5422                 g_warning ("%s: Account with no proto", __FUNCTION__);
5423                 return;
5424         }
5425
5426         /* Show the appropriate message text for the GError: */
5427         switch (err->code) {
5428         case TNY_SERVICE_ERROR_CONNECT:
5429                 message = modest_protocol_get_translation (protocol,
5430                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
5431                                                            server_name);
5432                 break;
5433         case TNY_SERVICE_ERROR_SEND:
5434                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
5435                 break;
5436         case TNY_SERVICE_ERROR_UNAVAILABLE:
5437                 message = modest_protocol_get_translation (protocol,
5438                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
5439                                                            server_name);
5440                 break;
5441         default:
5442                 g_warning ("%s: unexpected ERROR %d",
5443                            __FUNCTION__, err->code);
5444                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
5445                 break;
5446         }
5447
5448         modest_platform_run_information_dialog (NULL, message, FALSE);
5449         g_free (message);
5450 }
5451
5452 void
5453 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5454                                                 gchar *msg_id,
5455                                                 guint status,
5456                                                 gpointer user_data)
5457 {
5458         ModestWindow *top_window = NULL;
5459         ModestWindowMgr *mgr = NULL;
5460         GtkWidget *header_view = NULL;
5461         TnyFolder *selected_folder = NULL;
5462         TnyFolderType folder_type;
5463
5464         mgr = modest_runtime_get_window_mgr ();
5465         top_window = modest_window_mgr_get_current_top (mgr);
5466
5467         if (!top_window)
5468                 return;
5469
5470         if (MODEST_IS_HEADER_WINDOW (top_window)) {
5471                 header_view = (GtkWidget *)
5472                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
5473         }
5474
5475         /* Get selected folder */
5476         if (header_view)
5477                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
5478         if (!selected_folder)
5479                 return;
5480
5481         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5482 #if GTK_CHECK_VERSION(2, 8, 0)
5483         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
5484         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
5485                 GtkTreeViewColumn *tree_column;
5486
5487                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5488                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5489                 if (tree_column)
5490                         gtk_tree_view_column_queue_resize (tree_column);
5491                 }
5492 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
5493         gtk_widget_queue_draw (header_view);
5494 #endif
5495
5496 #ifndef MODEST_TOOLKIT_HILDON2
5497         /* Rerun dimming rules, because the message could become deletable for example */
5498         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5499                                                  MODEST_DIMMING_RULES_TOOLBAR);
5500         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5501                                                  MODEST_DIMMING_RULES_MENU);
5502 #endif
5503
5504         /* Free */
5505         g_object_unref (selected_folder);
5506 }
5507
5508 void
5509 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5510                                                TnyAccount *account)
5511 {
5512         ModestProtocolType protocol_type;
5513         ModestProtocol *protocol;
5514         gchar *error_note = NULL;
5515
5516         protocol_type = modest_tny_account_get_protocol_type (account);
5517         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5518                                                                   protocol_type);
5519
5520         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
5521         if (error_note == NULL) {
5522                 g_warning ("%s: This should not be reached", __FUNCTION__);
5523         } else {
5524                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5525                 g_free (error_note);
5526         }
5527 }
5528
5529 gchar *
5530 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5531 {
5532         gchar *msg = NULL;
5533         gchar *subject;
5534         TnyFolderStore *folder = NULL;
5535         TnyAccount *account = NULL;
5536         ModestProtocolType proto;
5537         ModestProtocol *protocol;
5538         TnyHeader *header = NULL;
5539
5540         if (MODEST_IS_HEADER_WINDOW (win)) {
5541                 GtkWidget *header_view;
5542                 TnyList* headers = NULL;
5543                 TnyIterator *iter;
5544                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
5545                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5546                 if (!headers || tny_list_get_length (headers) == 0) {
5547                         if (headers)
5548                                 g_object_unref (headers);
5549                         return NULL;
5550                 }
5551                 iter = tny_list_create_iterator (headers);
5552                 header = TNY_HEADER (tny_iterator_get_current (iter));
5553                 if (header) {
5554                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5555                 } else {
5556                         g_warning ("List should contain headers");
5557                 }
5558                 g_object_unref (iter);
5559                 g_object_unref (headers);
5560         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5561                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5562                 if (header)
5563                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5564         }
5565
5566         if (!header || !folder)
5567                 goto frees;
5568
5569         /* Get the account type */
5570         account = tny_folder_get_account (TNY_FOLDER (folder));
5571         proto = modest_tny_account_get_protocol_type (account);
5572         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5573                                                                   proto);
5574
5575         subject = tny_header_dup_subject (header);
5576         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
5577         if (subject)
5578                 g_free (subject);
5579         if (msg == NULL) {
5580                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5581         }
5582
5583  frees:
5584         /* Frees */
5585         if (account)
5586                 g_object_unref (account);
5587         if (folder)
5588                 g_object_unref (folder);
5589         if (header)
5590                 g_object_unref (header);
5591
5592         return msg;
5593 }
5594
5595 gboolean
5596 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
5597                                      const gchar *account_name,
5598                                      const gchar *account_title)
5599 {
5600         ModestAccountMgr *account_mgr;
5601         gchar *txt = NULL;
5602         gint response;
5603         ModestProtocol *protocol;
5604         gboolean removed = FALSE;
5605
5606         g_return_val_if_fail (account_name, FALSE);
5607         g_return_val_if_fail (account_title, FALSE);
5608
5609         account_mgr = modest_runtime_get_account_mgr();
5610
5611         /* The warning text depends on the account type: */
5612         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5613                                                                   modest_account_mgr_get_store_protocol (account_mgr,
5614                                                                                                          account_name));
5615         txt = modest_protocol_get_translation (protocol,
5616                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
5617                                                account_title);
5618         if (txt == NULL)
5619                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
5620
5621         response = modest_platform_run_confirmation_dialog (parent_window, txt);
5622         g_free (txt);
5623         txt = NULL;
5624
5625         if (response == GTK_RESPONSE_OK) {
5626                 /* Remove account. If it succeeds then it also removes
5627                    the account from the ModestAccountView: */
5628                 gboolean is_default = FALSE;
5629                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
5630                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
5631                         is_default = TRUE;
5632                 g_free (default_account_name);
5633
5634                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
5635                 if (removed) {
5636                         /* Close all email notifications, we cannot
5637                            distinguish if the notification belongs to
5638                            this account or not, so for safety reasons
5639                            we remove them all */
5640                         modest_platform_remove_new_mail_notifications (FALSE);
5641                 } else {
5642                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
5643                 }
5644         }
5645         return removed;
5646 }
5647
5648 static void
5649 on_fetch_images_performer (gboolean canceled,
5650                            GError *err,
5651                            GtkWindow *parent_window,
5652                            TnyAccount *account,
5653                            gpointer user_data)
5654 {
5655         if (err || canceled) {
5656                 /* Show an unable to retrieve images ??? */
5657                 return;
5658         }
5659
5660         /* Note that the user could have closed the window while connecting */
5661         if (GTK_WIDGET_VISIBLE (parent_window))
5662                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
5663         g_object_unref ((GObject *) user_data);
5664 }
5665
5666 void
5667 modest_ui_actions_on_fetch_images (GtkAction *action,
5668                                    ModestWindow *window)
5669 {
5670         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
5671
5672         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
5673                                              NULL,
5674                                              on_fetch_images_performer, 
5675                                              g_object_ref (window));
5676 }
5677
5678 void
5679 modest_ui_actions_on_reload_message (const gchar *msg_id)
5680 {
5681         ModestWindow *window = NULL;
5682
5683         g_return_if_fail (msg_id && msg_id[0] != '\0');
5684         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
5685                                                             msg_id,
5686                                                             &window))
5687                 return;
5688
5689
5690         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
5691                 return;
5692
5693         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
5694 }
5695
5696 /** Check whether any connections are active, and cancel them if 
5697  * the user wishes.
5698  * Returns TRUE is there was no problem, 
5699  * or if an operation was cancelled so we can continue.
5700  * Returns FALSE if the user chose to cancel his request instead.
5701  */
5702
5703 gboolean
5704 modest_ui_actions_check_for_active_account (ModestWindow *self,
5705                                             const gchar* account_name)
5706 {
5707         ModestTnySendQueue *send_queue;
5708         ModestTnyAccountStore *acc_store;
5709         ModestMailOperationQueue* queue;
5710         TnyConnectionStatus store_conn_status;
5711         TnyAccount *store_account = NULL, *transport_account = NULL;
5712         gboolean retval = TRUE, sending = FALSE;
5713
5714         acc_store = modest_runtime_get_account_store ();
5715         queue = modest_runtime_get_mail_operation_queue ();
5716
5717         store_account = 
5718                 modest_tny_account_store_get_server_account (acc_store,
5719                                                              account_name,
5720                                                              TNY_ACCOUNT_TYPE_STORE);
5721
5722         /* This could happen if the account was deleted before the
5723            call to this function */
5724         if (!store_account)
5725                 return FALSE;
5726
5727         transport_account = 
5728                 modest_tny_account_store_get_server_account (acc_store,
5729                                                              account_name,
5730                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
5731
5732         /* This could happen if the account was deleted before the
5733            call to this function */
5734         if (!transport_account) {
5735                 g_object_unref (store_account);
5736                 return FALSE;
5737         }
5738
5739         /* If the transport account was not used yet, then the send
5740            queue could not exist (it's created on demand) */
5741         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
5742         if (TNY_IS_SEND_QUEUE (send_queue))
5743                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
5744
5745         store_conn_status = tny_account_get_connection_status (store_account);
5746         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
5747                 gint response;
5748
5749                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
5750                                                                 _("emev_nc_disconnect_account"));
5751                 if (response == GTK_RESPONSE_OK) {
5752                         retval = TRUE;
5753                 } else {
5754                         retval = FALSE;
5755                 }
5756         }
5757
5758         if (retval) {
5759
5760                 /* FIXME: We should only cancel those of this account */
5761                 modest_mail_operation_queue_cancel_all (queue);
5762
5763                 /* Also disconnect the account */
5764                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
5765                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
5766                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
5767                                                       FALSE, NULL, NULL);
5768                 }
5769                 if (sending) {
5770                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
5771                                                       FALSE, NULL, NULL);
5772                 }
5773         }
5774                 
5775         /* Frees */
5776         g_object_unref (store_account);
5777         g_object_unref (transport_account);
5778         
5779         return retval;
5780 }