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