Move connection specific smtp edit window to src/widgets
[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         modest_msg_edit_window_select_background_color (window);
2867 }
2868
2869 void
2870 modest_ui_actions_on_insert_image (GObject *object,
2871                                    ModestMsgEditWindow *window)
2872 {
2873         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2874
2875
2876         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2877                 return;
2878
2879         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2880                 return;
2881
2882         modest_msg_edit_window_insert_image (window);
2883 }
2884
2885 void
2886 modest_ui_actions_on_attach_file (GtkAction *action,
2887                                   ModestMsgEditWindow *window)
2888 {
2889         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2890         g_return_if_fail (GTK_IS_ACTION (action));
2891
2892         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2893                 return;
2894
2895         modest_msg_edit_window_offer_attach_file (window);
2896 }
2897
2898 void
2899 modest_ui_actions_on_remove_attachments (GtkAction *action,
2900                                          ModestMsgEditWindow *window)
2901 {
2902         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2903
2904         modest_msg_edit_window_remove_attachments (window, NULL);
2905 }
2906
2907 static void
2908 do_create_folder_cb (ModestMailOperation *mail_op,
2909                      TnyFolderStore *parent_folder,
2910                      TnyFolder *new_folder,
2911                      gpointer user_data)
2912 {
2913         gchar *suggested_name = (gchar *) user_data;
2914         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2915         const GError *error;
2916
2917         error = modest_mail_operation_get_error (mail_op);
2918         if (error) {
2919                 gboolean disk_full = FALSE;
2920                 TnyAccount *account;
2921                 /* Show an error. If there was some problem writing to
2922                    disk, show it, otherwise show the generic folder
2923                    create error. We do it here and not in an error
2924                    handler because the call to do_create_folder will
2925                    stop the main loop in a gtk_dialog_run and then,
2926                    the message won't be shown until that dialog is
2927                    closed */
2928                 account = modest_mail_operation_get_account (mail_op);
2929                 if (account) {
2930                         disk_full =
2931                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2932                                                                                 (GtkWidget *) source_win,
2933                                                                                 (GError *) error,
2934                                                                                 account,
2935                                                                                 _("mail_in_ui_folder_create_error_memory"));
2936                         g_object_unref (account);
2937                 }
2938                 if (!disk_full) {
2939                         /* Show an error and try again if there is no
2940                            full memory condition */
2941                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
2942                                                             _("mail_in_ui_folder_create_error"));
2943                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2944                 }
2945
2946         } else {
2947                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2948                  * FIXME: any other? */
2949                 GtkWidget *folder_view;
2950
2951                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
2952                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
2953
2954                 /* Select the newly created folder. It could happen
2955                    that the widget is no longer there (i.e. the window
2956                    has been destroyed, so we need to check this */
2957                 if (folder_view)
2958                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2959                                                           new_folder, FALSE);
2960                 g_object_unref (new_folder);
2961         }
2962         /* Free. Note that the first time it'll be NULL so noop */
2963         g_free (suggested_name);
2964         g_object_unref (source_win);
2965 }
2966
2967 typedef struct {
2968         gchar *folder_name;
2969         TnyFolderStore *parent;
2970 } CreateFolderConnect;
2971
2972 static void
2973 do_create_folder_performer (gboolean canceled,
2974                          GError *err,
2975                          GtkWindow *parent_window,
2976                          TnyAccount *account,
2977                          gpointer user_data)
2978 {
2979         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
2980         ModestMailOperation *mail_op;
2981
2982         if (canceled || err) {
2983                 /* In disk full conditions we could get this error here */
2984                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2985                                                                 (GtkWidget *) parent_window, err,
2986                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
2987
2988                 /* This happens if we have selected the outbox folder
2989                    as the parent */
2990                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
2991                     TNY_IS_MERGE_FOLDER (helper->parent)) {
2992                         /* Show an error and retry */
2993                         modest_platform_information_banner ((GtkWidget *) parent_window,
2994                                                             NULL,
2995                                                             _("mail_in_ui_folder_create_error"));
2996
2997                         do_create_folder (parent_window, helper->parent, helper->folder_name);
2998                 }
2999
3000                 goto frees;
3001         }
3002
3003         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3004         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3005                                          mail_op);
3006         modest_mail_operation_create_folder (mail_op,
3007                                              helper->parent,
3008                                              (const gchar *) helper->folder_name,
3009                                              do_create_folder_cb,
3010                                              g_strdup (helper->folder_name));
3011         g_object_unref (mail_op);
3012
3013  frees:
3014         if (helper->parent)
3015                 g_object_unref (helper->parent);
3016         if (helper->folder_name)
3017                 g_free (helper->folder_name);
3018         g_slice_free (CreateFolderConnect, helper);
3019 }
3020
3021
3022 static void
3023 do_create_folder (GtkWindow *parent_window,
3024                   TnyFolderStore *suggested_parent,
3025                   const gchar *suggested_name)
3026 {
3027         gint result;
3028         gchar *folder_name = NULL;
3029         TnyFolderStore *parent_folder = NULL;
3030
3031         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3032                                                         suggested_parent,
3033                                                         (gchar *) suggested_name,
3034                                                         &folder_name,
3035                                                         &parent_folder);
3036
3037         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3038                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3039                 helper->folder_name = g_strdup (folder_name);
3040                 helper->parent = g_object_ref (parent_folder);
3041
3042                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3043                                                                TRUE,
3044                                                                parent_folder,
3045                                                                do_create_folder_performer,
3046                                                                helper);
3047         }
3048
3049         if (folder_name)
3050                 g_free (folder_name);
3051         if (parent_folder)
3052                 g_object_unref (parent_folder);
3053 }
3054
3055 static void
3056 modest_ui_actions_create_folder(GtkWidget *parent_window,
3057                                 GtkWidget *folder_view,
3058                                 TnyFolderStore *parent_folder)
3059 {
3060         if (!parent_folder) {
3061                 ModestTnyAccountStore *acc_store;
3062
3063                 acc_store = modest_runtime_get_account_store ();
3064
3065                 parent_folder = (TnyFolderStore *)
3066                         modest_tny_account_store_get_local_folders_account (acc_store);
3067         }
3068
3069         if (parent_folder) {
3070                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3071                 g_object_unref (parent_folder);
3072         }
3073 }
3074
3075 void
3076 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3077 {
3078
3079         g_return_if_fail (MODEST_IS_WINDOW(window));
3080
3081         if (MODEST_IS_FOLDER_WINDOW (window)) {
3082                 GtkWidget *folder_view;
3083
3084                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3085                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3086         } else {
3087                 g_assert_not_reached ();
3088         }
3089 }
3090
3091 static void
3092 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3093                                                gpointer user_data)
3094 {
3095         const GError *error = NULL;
3096         gchar *message = NULL;
3097         gboolean mem_full;
3098         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3099
3100         /* Get error message */
3101         error = modest_mail_operation_get_error (mail_op);
3102         if (!error)
3103                 g_return_if_reached ();
3104
3105         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3106                                                                 (GError *) error, account);
3107         if (mem_full) {
3108                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3109         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3110                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3111                 message = _CS("ckdg_ib_folder_already_exists");
3112         } else if (error->domain == TNY_ERROR_DOMAIN &&
3113                    error->code == TNY_SERVICE_ERROR_STATE) {
3114                 /* This means that the folder is already in use (a
3115                    message is opened for example */
3116                 message = _("emev_ni_internal_error");
3117         } else {
3118                 message = _CS("ckdg_ib_unable_to_rename");
3119         }
3120
3121         /* We don't set a parent for the dialog because the dialog
3122            will be destroyed so the banner won't appear */
3123         modest_platform_information_banner (NULL, NULL, message);
3124
3125         if (account)
3126                 g_object_unref (account);
3127         if (mem_full)
3128                 g_free (message);
3129 }
3130
3131 typedef struct {
3132         TnyFolderStore *folder;
3133         gchar *new_name;
3134 } RenameFolderInfo;
3135
3136 static void
3137 on_rename_folder_cb (ModestMailOperation *mail_op,
3138                      TnyFolder *new_folder,
3139                      gpointer user_data)
3140 {
3141         ModestFolderView *folder_view;
3142
3143         /* If the window was closed when renaming a folder, or if
3144          * it's not a main window this will happen */
3145         if (!MODEST_IS_FOLDER_VIEW (user_data))
3146                 return;
3147
3148         folder_view = MODEST_FOLDER_VIEW (user_data);
3149         /* Note that if the rename fails new_folder will be NULL */
3150         if (new_folder) {
3151                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3152 #ifndef MODEST_TOOLKIT_HILDON2
3153         } else {
3154                 modest_folder_view_select_first_inbox_or_local (folder_view);
3155 #endif
3156         }
3157         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3158 }
3159
3160 static void
3161 on_rename_folder_performer (gboolean canceled,
3162                             GError *err,
3163                             GtkWindow *parent_window,
3164                             TnyAccount *account,
3165                             gpointer user_data)
3166 {
3167         ModestMailOperation *mail_op = NULL;
3168         GtkTreeSelection *sel = NULL;
3169         GtkWidget *folder_view = NULL;
3170         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3171
3172         if (canceled || err) {
3173                 /* In disk full conditions we could get this error here */
3174                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3175                                                                 (GtkWidget *) parent_window, err,
3176                                                                 account, NULL);
3177         } else {
3178
3179                 mail_op =
3180                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3181                                         modest_ui_actions_rename_folder_error_handler,
3182                                         parent_window, NULL);
3183
3184                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3185                                 mail_op);
3186                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3187                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3188                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3189                 }
3190
3191                 /* Clear the folders view */
3192                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3193                 gtk_tree_selection_unselect_all (sel);
3194
3195                 /* Actually rename the folder */
3196                 modest_mail_operation_rename_folder (mail_op,
3197                                                      TNY_FOLDER (data->folder),
3198                                                      (const gchar *) (data->new_name),
3199                                                      on_rename_folder_cb,
3200                                                      folder_view);
3201                 g_object_unref (mail_op);
3202         }
3203
3204         g_object_unref (data->folder);
3205         g_free (data->new_name);
3206         g_free (data);
3207 }
3208
3209 void
3210 modest_ui_actions_on_rename_folder (GtkAction *action,
3211                                      ModestWindow *window)
3212 {
3213         modest_ui_actions_on_edit_mode_rename_folder (window);
3214 }
3215
3216 gboolean
3217 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3218 {
3219         TnyFolderStore *folder;
3220         GtkWidget *folder_view;
3221         gboolean do_rename = TRUE;
3222
3223         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3224
3225         if (MODEST_IS_FOLDER_WINDOW (window)) {
3226                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3227         } else {
3228                 return FALSE;
3229         }
3230
3231         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3232
3233         if (!folder)
3234                 return FALSE;
3235
3236         if (TNY_IS_FOLDER (folder)) {
3237                 gchar *folder_name = NULL;
3238                 gint response;
3239                 const gchar *current_name;
3240                 TnyFolderStore *parent;
3241
3242                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3243                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3244                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3245                                                                      parent, current_name,
3246                                                                      &folder_name);
3247                 g_object_unref (parent);
3248
3249                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3250                         do_rename = FALSE;
3251                 } else {
3252                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3253                         rename_folder_data->folder = g_object_ref (folder);
3254                         rename_folder_data->new_name = folder_name;
3255                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3256                                         folder, on_rename_folder_performer, rename_folder_data);
3257                 }
3258         }
3259         g_object_unref (folder);
3260         return do_rename;
3261 }
3262
3263 static void
3264 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3265                                                gpointer user_data)
3266 {
3267         GObject *win = modest_mail_operation_get_source (mail_op);
3268
3269         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3270                                                 _("mail_in_ui_folder_delete_error"),
3271                                                 FALSE);
3272         g_object_unref (win);
3273 }
3274
3275 typedef struct {
3276         TnyFolderStore *folder;
3277         gboolean move_to_trash;
3278 } DeleteFolderInfo;
3279
3280 static void
3281 on_delete_folder_cb (gboolean canceled,
3282                   GError *err,
3283                   GtkWindow *parent_window,
3284                   TnyAccount *account,
3285                   gpointer user_data)
3286 {
3287         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3288         GtkWidget *folder_view;
3289         ModestMailOperation *mail_op;
3290         GtkTreeSelection *sel;
3291
3292         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3293                 /* Note that the connection process can fail due to
3294                    memory low conditions as it can not successfully
3295                    store the summary */
3296                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3297                                                                      (GtkWidget*) parent_window, err,
3298                                                                      account, NULL))
3299                         g_debug ("Error connecting when trying to delete a folder");
3300                 g_object_unref (G_OBJECT (info->folder));
3301                 g_free (info);
3302                 return;
3303         }
3304
3305         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3306                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3307         } else {
3308                 g_object_unref (G_OBJECT (info->folder));
3309                 g_free (info);
3310                 return;
3311         }
3312
3313         /* Unselect the folder before deleting it to free the headers */
3314         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3315         gtk_tree_selection_unselect_all (sel);
3316
3317         /* Create the mail operation */
3318         mail_op =
3319                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3320                                 modest_ui_actions_delete_folder_error_handler,
3321                                 NULL, NULL);
3322
3323         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3324                         mail_op);
3325         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3326
3327 #ifndef MODEST_TOOLKIT_HILDON2
3328         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3329 #endif
3330
3331         g_object_unref (mail_op);
3332         g_object_unref (info->folder);
3333         g_free (info);
3334 }
3335
3336 static gboolean
3337 delete_folder (ModestWindow *window, gboolean move_to_trash)
3338 {
3339         TnyFolderStore *folder;
3340         GtkWidget *folder_view;
3341         gint response;
3342         gchar *message;
3343
3344         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3345
3346         if (MODEST_IS_FOLDER_WINDOW (window)) {
3347                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3348         } else {
3349                 return FALSE;
3350         }
3351         if (!folder_view)
3352                 return FALSE;
3353
3354         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3355
3356         if (!folder)
3357                 return FALSE;
3358
3359         /* Show an error if it's an account */
3360         if (!TNY_IS_FOLDER (folder)) {
3361                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3362                                                         _("mail_in_ui_folder_delete_error"),
3363                                                         FALSE);
3364                 g_object_unref (G_OBJECT (folder));
3365                 return FALSE;
3366         }
3367
3368         /* Ask the user */
3369         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3370                                     tny_folder_get_name (TNY_FOLDER (folder)));
3371         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3372                                                             (const gchar *) message);
3373         g_free (message);
3374
3375         if (response == GTK_RESPONSE_OK) {
3376                 TnyAccount *account = NULL;
3377                 DeleteFolderInfo *info = NULL;
3378                 info = g_new0(DeleteFolderInfo, 1);
3379                 info->folder = g_object_ref (folder);
3380                 info->move_to_trash = move_to_trash;
3381
3382                 account = tny_folder_get_account (TNY_FOLDER (folder));
3383                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3384                                                                TRUE,
3385                                                                TNY_FOLDER_STORE (account),
3386                                                                on_delete_folder_cb, info);
3387                 g_object_unref (account);
3388                 g_object_unref (folder);
3389                 return TRUE;
3390         } else {
3391                 return FALSE;
3392         }
3393 }
3394
3395 void
3396 modest_ui_actions_on_delete_folder (GtkAction *action,
3397                                     ModestWindow *window)
3398 {
3399         modest_ui_actions_on_edit_mode_delete_folder (window);
3400 }
3401
3402 gboolean
3403 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3404 {
3405         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3406
3407         return delete_folder (window, FALSE);
3408 }
3409
3410
3411 typedef struct _PasswordDialogFields {
3412         GtkWidget *username;
3413         GtkWidget *password;
3414         GtkWidget *dialog;
3415 } PasswordDialogFields;
3416
3417 static void
3418 password_dialog_check_field (GtkEditable *editable,
3419                              PasswordDialogFields *fields)
3420 {
3421         const gchar *value;
3422         gboolean any_value_empty = FALSE;
3423
3424         value = modest_entry_get_text (fields->username);
3425         if ((value == NULL) || value[0] == '\0') {
3426                 any_value_empty = TRUE;
3427         }
3428         value = modest_entry_get_text (fields->password);
3429         if ((value == NULL) || value[0] == '\0') {
3430                 any_value_empty = TRUE;
3431         }
3432         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3433 }
3434
3435 void
3436 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3437                                          const gchar* server_account_name,
3438                                          gchar **username,
3439                                          gchar **password,
3440                                          gboolean *cancel,
3441                                          gboolean *remember,
3442                                          ModestMainWindow *main_window)
3443 {
3444         g_return_if_fail(server_account_name);
3445         gboolean completed = FALSE;
3446         PasswordDialogFields *fields = NULL;
3447
3448         /* Initalize output parameters: */
3449         if (cancel)
3450                 *cancel = FALSE;
3451
3452         if (remember)
3453                 *remember = TRUE;
3454
3455 #ifndef MODEST_TOOLKIT_GTK
3456         /* Maemo uses a different (awkward) button order,
3457          * It should probably just use gtk_alternative_dialog_button_order ().
3458          */
3459 #ifdef MODEST_TOOLKIT_HILDON2
3460         GtkWidget *dialog =
3461                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3462                                              NULL,
3463                                              GTK_DIALOG_MODAL,
3464                                              _HL("wdgt_bd_done"),
3465                                              GTK_RESPONSE_ACCEPT,
3466                                              NULL);
3467         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3468                                         HILDON_MARGIN_DOUBLE);
3469 #else
3470         GtkWidget *dialog =
3471                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3472                                              NULL,
3473                                              GTK_DIALOG_MODAL,
3474                                              _("mcen_bd_dialog_ok"),
3475                                              GTK_RESPONSE_ACCEPT,
3476                                              _("mcen_bd_dialog_cancel"),
3477                                              GTK_RESPONSE_REJECT,
3478                                              NULL);
3479 #endif /* MODEST_TOOLKIT_HILDON2 */
3480 #else
3481         GtkWidget *dialog =
3482                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3483                                              NULL,
3484                                              GTK_DIALOG_MODAL,
3485                                              GTK_STOCK_CANCEL,
3486                                              GTK_RESPONSE_REJECT,
3487                                              GTK_STOCK_OK,
3488                                              GTK_RESPONSE_ACCEPT,
3489                                              NULL);
3490 #endif /* MODEST_TOOLKIT_GTK */
3491
3492         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3493
3494         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3495                 modest_runtime_get_account_mgr(), server_account_name);
3496         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3497                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3498                 if (cancel)
3499                         *cancel = TRUE;
3500                 gtk_widget_destroy (dialog);
3501                 return;
3502         }
3503
3504         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3505         GtkWidget *label = gtk_label_new (txt);
3506         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3507         g_free (txt);
3508         g_free (server_name);
3509         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3510                             FALSE, FALSE, 0);
3511         server_name = NULL;
3512
3513         /* username: */
3514         gchar *initial_username = modest_account_mgr_get_server_account_username (
3515                 modest_runtime_get_account_mgr(), server_account_name);
3516
3517         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
3518         if (initial_username)
3519                 modest_entry_set_text (entry_username, initial_username);
3520
3521         /* Dim this if a connection has ever succeeded with this username,
3522          * as per the UI spec: */
3523         /* const gboolean username_known =  */
3524         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3525         /*              modest_runtime_get_account_mgr(), server_account_name); */
3526         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3527
3528         /* We drop the username sensitive code and disallow changing it here
3529          * as tinymail does not support really changing the username in the callback
3530          */
3531         gtk_widget_set_sensitive (entry_username, FALSE);
3532
3533         /* Auto-capitalization is the default, so let's turn it off: */
3534 #ifdef MAEMO_CHANGES
3535         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3536 #endif
3537
3538         /* Create a size group to be used by all captions.
3539          * Note that HildonCaption does not create a default size group if we do not specify one.
3540          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3541         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3542
3543         GtkWidget *caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
3544                                                                     _("mail_fi_username"), FALSE,
3545                                                                     entry_username);
3546         gtk_widget_show (entry_username);
3547         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3548                 FALSE, FALSE, MODEST_MARGIN_HALF);
3549         gtk_widget_show (caption);
3550
3551         /* password: */
3552         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
3553         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3554         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3555
3556         /* Auto-capitalization is the default, so let's turn it off: */
3557 #ifdef MAEMO_CHANGES
3558         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3559                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3560 #endif
3561
3562         caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
3563                                                          _("mail_fi_password"), FALSE,
3564                                                          entry_password);
3565         gtk_widget_show (entry_password);
3566         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3567                 FALSE, FALSE, MODEST_MARGIN_HALF);
3568         gtk_widget_show (caption);
3569         g_object_unref (sizegroup);
3570
3571         if (initial_username != NULL)
3572                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3573
3574 /* This is not in the Maemo UI spec:
3575         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3576         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3577                             TRUE, FALSE, 0);
3578 */
3579
3580         fields = g_slice_new0 (PasswordDialogFields);
3581         fields->username = entry_username;
3582         fields->password = entry_password;
3583         fields->dialog = dialog;
3584
3585         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3586         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3587         password_dialog_check_field (NULL, fields);
3588
3589         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3590
3591         while (!completed) {
3592
3593                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3594                         if (username) {
3595                                 *username = g_strdup (modest_entry_get_text (entry_username));
3596
3597                                 /* Note that an empty field becomes the "" string */
3598                                 if (*username && strlen (*username) > 0) {
3599                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3600                                                                                         server_account_name,
3601                                                                                         *username);
3602                                         completed = TRUE;
3603
3604                                         const gboolean username_was_changed =
3605                                                 (strcmp (*username, initial_username) != 0);
3606                                         if (username_was_changed) {
3607                                                 g_warning ("%s: tinymail does not yet support changing the "
3608                                                            "username in the get_password() callback.\n", __FUNCTION__);
3609                                         }
3610                                 } else {
3611                                         g_free (*username);
3612                                         *username = NULL;
3613                                         /* Show error */
3614                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3615                                                                             _("mcen_ib_username_pw_incorrect"));
3616                                         completed = FALSE;
3617                                 }
3618                         }
3619
3620                         if (password) {
3621                                 *password = g_strdup (modest_entry_get_text (entry_password));
3622
3623                                 /* We do not save the password in the configuration,
3624                                  * because this function is only called for passwords that should
3625                                  * not be remembered:
3626                                  modest_server_account_set_password (
3627                                  modest_runtime_get_account_mgr(), server_account_name,
3628                                  *password);
3629                                  */
3630                         }
3631                         if (cancel)
3632                                 *cancel   = FALSE;
3633                 } else {
3634                         completed = TRUE;
3635                         if (username)
3636                                 *username = NULL;
3637                         if (password)
3638                                 *password = NULL;
3639                         if (cancel)
3640                                 *cancel   = TRUE;
3641                 }
3642         }
3643
3644 /* This is not in the Maemo UI spec:
3645         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3646                 *remember = TRUE;
3647         else
3648                 *remember = FALSE;
3649 */
3650
3651         g_free (initial_username);
3652         gtk_widget_destroy (dialog);
3653         g_slice_free (PasswordDialogFields, fields);
3654
3655         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3656 }
3657
3658 void
3659 modest_ui_actions_on_cut (GtkAction *action,
3660                           ModestWindow *window)
3661 {
3662         GtkWidget *focused_widget;
3663         GtkClipboard *clipboard;
3664
3665         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3666         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3667         if (GTK_IS_EDITABLE (focused_widget)) {
3668                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3669                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3670                 gtk_clipboard_store (clipboard);
3671         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3672                 GtkTextBuffer *buffer;
3673
3674                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3675                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3676                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3677                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3678                         gtk_clipboard_store (clipboard);
3679                 }
3680         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3681                 TnyList *header_list = modest_header_view_get_selected_headers (
3682                                 MODEST_HEADER_VIEW (focused_widget));
3683                 gboolean continue_download = FALSE;
3684                 gint num_of_unc_msgs;
3685
3686                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3687
3688                 if (num_of_unc_msgs) {
3689                         TnyAccount *account = get_account_from_header_list (header_list);
3690                         if (account) {
3691                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3692                                 g_object_unref (account);
3693                         }
3694                 }
3695
3696                 if (num_of_unc_msgs == 0 || continue_download) {
3697 /*                      modest_platform_information_banner (
3698                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3699                         modest_header_view_cut_selection (
3700                                         MODEST_HEADER_VIEW (focused_widget));
3701                 }
3702
3703                 g_object_unref (header_list);
3704         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3705                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3706         }
3707 }
3708
3709 void
3710 modest_ui_actions_on_copy (GtkAction *action,
3711                            ModestWindow *window)
3712 {
3713         GtkClipboard *clipboard;
3714         GtkWidget *focused_widget;
3715         gboolean copied = TRUE;
3716
3717         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3718         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3719
3720         if (GTK_IS_LABEL (focused_widget)) {
3721                 gchar *selection;
3722                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3723                 gtk_clipboard_set_text (clipboard, selection, -1);
3724                 g_free (selection);
3725                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3726                 gtk_clipboard_store (clipboard);
3727         } else if (GTK_IS_EDITABLE (focused_widget)) {
3728                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3729                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3730                 gtk_clipboard_store (clipboard);
3731         } else if (GTK_IS_HTML (focused_widget)) {
3732                 const gchar *sel;
3733                 int len = -1;
3734                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3735                 if ((sel == NULL) || (sel[0] == '\0')) {
3736                         copied = FALSE;
3737                 } else {
3738                         gtk_html_copy (GTK_HTML (focused_widget));
3739                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3740                         gtk_clipboard_store (clipboard);
3741                 }
3742         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3743                 GtkTextBuffer *buffer;
3744                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3745                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3746                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3747                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3748                         gtk_clipboard_store (clipboard);
3749                 }
3750         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3751                 TnyList *header_list = modest_header_view_get_selected_headers (
3752                                 MODEST_HEADER_VIEW (focused_widget));
3753                 gboolean continue_download = FALSE;
3754                 gint num_of_unc_msgs;
3755
3756                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3757
3758                 if (num_of_unc_msgs) {
3759                         TnyAccount *account = get_account_from_header_list (header_list);
3760                         if (account) {
3761                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3762                                 g_object_unref (account);
3763                         }
3764                 }
3765
3766                 if (num_of_unc_msgs == 0 || continue_download) {
3767                         modest_platform_information_banner (
3768                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3769                         modest_header_view_copy_selection (
3770                                         MODEST_HEADER_VIEW (focused_widget));
3771                 } else
3772                         copied = FALSE;
3773
3774                 g_object_unref (header_list);
3775
3776         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3777                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3778         }
3779
3780         /* Show information banner if there was a copy to clipboard */
3781         if(copied)
3782                 modest_platform_information_banner (
3783                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3784 }
3785
3786 void
3787 modest_ui_actions_on_undo (GtkAction *action,
3788                            ModestWindow *window)
3789 {
3790         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3791                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3792 #ifndef MODEST_TOOLKIT_HILDON2
3793         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3794                 ModestEmailClipboard *clipboard = NULL;
3795                 /* Clear clipboard source */
3796                 clipboard = modest_runtime_get_email_clipboard ();
3797                 modest_email_clipboard_clear (clipboard);
3798 #endif
3799         } else {
3800                 g_return_if_reached ();
3801         }
3802 }
3803
3804 void
3805 modest_ui_actions_on_redo (GtkAction *action,
3806                            ModestWindow *window)
3807 {
3808         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3809                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3810         }
3811         else {
3812                 g_return_if_reached ();
3813         }
3814 }
3815
3816
3817 static void
3818 destroy_information_note (ModestMailOperation *mail_op,
3819                           gpointer user_data)
3820 {
3821         /* destroy information note */
3822         gtk_widget_destroy (GTK_WIDGET(user_data));
3823 }
3824
3825 static void
3826 destroy_folder_information_note (ModestMailOperation *mail_op,
3827                                  TnyFolder *new_folder,
3828                                  gpointer user_data)
3829 {
3830         /* destroy information note */
3831         gtk_widget_destroy (GTK_WIDGET(user_data));
3832 }
3833
3834
3835 static void
3836 paste_as_attachment_free (gpointer data)
3837 {
3838         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3839
3840         if (helper->banner) {
3841                 gtk_widget_destroy (helper->banner);
3842                 g_object_unref (helper->banner);
3843         }
3844         g_free (helper);
3845 }
3846
3847 static void
3848 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3849                             TnyHeader *header,
3850                             TnyMsg *msg,
3851                             gpointer userdata)
3852 {
3853         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3854         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3855
3856         if (msg == NULL)
3857                 return;
3858
3859         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3860
3861 }
3862
3863 void
3864 modest_ui_actions_on_paste (GtkAction *action,
3865                             ModestWindow *window)
3866 {
3867         GtkWidget *focused_widget = NULL;
3868         GtkWidget *inf_note = NULL;
3869         ModestMailOperation *mail_op = NULL;
3870
3871         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3872         if (GTK_IS_EDITABLE (focused_widget)) {
3873                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3874         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3875                 ModestEmailClipboard *e_clipboard = NULL;
3876                 e_clipboard = modest_runtime_get_email_clipboard ();
3877                 if (modest_email_clipboard_cleared (e_clipboard)) {
3878                         GtkTextBuffer *buffer;
3879                         GtkClipboard *clipboard;
3880
3881                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3882                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3883                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3884                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3885                         ModestMailOperation *mail_op;
3886                         TnyFolder *src_folder = NULL;
3887                         TnyList *data = NULL;
3888                         gboolean delete;
3889                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3890                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3891                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3892                                                                            _CS("ckct_nw_pasting"));
3893                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3894                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3895                         if (helper->banner != NULL) {
3896                                 g_object_ref (G_OBJECT (helper->banner));
3897                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3898                         }
3899
3900                         if (data != NULL) {
3901                                 modest_mail_operation_get_msgs_full (mail_op,
3902                                                                      data,
3903                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3904                                                                      helper,
3905                                                                      paste_as_attachment_free);
3906                         }
3907                         /* Free */
3908                         if (data)
3909                                 g_object_unref (data);
3910                         if (src_folder)
3911                                 g_object_unref (src_folder);
3912
3913                 }
3914         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3915                 ModestEmailClipboard *clipboard = NULL;
3916                 TnyFolder *src_folder = NULL;
3917                 TnyFolderStore *folder_store = NULL;
3918                 TnyList *data = NULL;
3919                 gboolean delete = FALSE;
3920
3921                 /* Check clipboard source */
3922                 clipboard = modest_runtime_get_email_clipboard ();
3923                 if (modest_email_clipboard_cleared (clipboard))
3924                         return;
3925
3926                 /* Get elements to paste */
3927                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3928
3929                 /* Create a new mail operation */
3930                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3931
3932                 /* Get destination folder */
3933                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3934
3935                 /* transfer messages  */
3936                 if (data != NULL) {
3937                         gint response = 0;
3938
3939                         /* Ask for user confirmation */
3940                         response =
3941                                 modest_ui_actions_msgs_move_to_confirmation (window,
3942                                                                              TNY_FOLDER (folder_store),
3943                                                                              delete,
3944                                                                              data);
3945
3946                         if (response == GTK_RESPONSE_OK) {
3947                                 /* Launch notification */
3948                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3949                                                                              _CS("ckct_nw_pasting"));
3950                                 if (inf_note != NULL)  {
3951                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3952                                         gtk_widget_show (GTK_WIDGET(inf_note));
3953                                 }
3954
3955                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3956                                 modest_mail_operation_xfer_msgs (mail_op,
3957                                                                  data,
3958                                                                  TNY_FOLDER (folder_store),
3959                                                                  delete,
3960                                                                  destroy_information_note,
3961                                                                  inf_note);
3962                         } else {
3963                                 g_object_unref (mail_op);
3964                         }
3965
3966                 } else if (src_folder != NULL) {
3967                         /* Launch notification */
3968                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3969                                                                      _CS("ckct_nw_pasting"));
3970                         if (inf_note != NULL)  {
3971                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3972                                 gtk_widget_show (GTK_WIDGET(inf_note));
3973                         }
3974
3975                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3976                         modest_mail_operation_xfer_folder (mail_op,
3977                                                            src_folder,
3978                                                            folder_store,
3979                                                            delete,
3980                                                            destroy_folder_information_note,
3981                                                            inf_note);
3982                 }
3983
3984                 /* Free */
3985                 if (data != NULL)
3986                         g_object_unref (data);
3987                 if (src_folder != NULL)
3988                         g_object_unref (src_folder);
3989                 if (folder_store != NULL)
3990                         g_object_unref (folder_store);
3991         }
3992 }
3993
3994
3995 void
3996 modest_ui_actions_on_select_all (GtkAction *action,
3997                                  ModestWindow *window)
3998 {
3999         GtkWidget *focused_widget;
4000
4001         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4002         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4003                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4004         } else if (GTK_IS_LABEL (focused_widget)) {
4005                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4006         } else if (GTK_IS_EDITABLE (focused_widget)) {
4007                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4008         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4009                 GtkTextBuffer *buffer;
4010                 GtkTextIter start, end;
4011
4012                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4013                 gtk_text_buffer_get_start_iter (buffer, &start);
4014                 gtk_text_buffer_get_end_iter (buffer, &end);
4015                 gtk_text_buffer_select_range (buffer, &start, &end);
4016         } else if (GTK_IS_HTML (focused_widget)) {
4017                 gtk_html_select_all (GTK_HTML (focused_widget));
4018 #ifndef MODEST_TOOLKIT_HILDON2
4019         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4020                 GtkWidget *header_view = focused_widget;
4021                 GtkTreeSelection *selection = NULL;
4022
4023                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4024                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4025                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4026                 }
4027
4028                 /* Disable window dimming management */
4029                 modest_window_disable_dimming (MODEST_WINDOW(window));
4030
4031                 /* Select all messages */
4032                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4033                 gtk_tree_selection_select_all (selection);
4034
4035                 /* Set focuse on header view */
4036                 gtk_widget_grab_focus (header_view);
4037
4038                 /* Enable window dimming management */
4039                 modest_window_enable_dimming (MODEST_WINDOW(window));
4040                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4041                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4042 #endif
4043         }
4044
4045 }
4046
4047 void
4048 modest_ui_actions_on_mark_as_read (GtkAction *action,
4049                                    ModestWindow *window)
4050 {
4051         g_return_if_fail (MODEST_IS_WINDOW(window));
4052
4053         /* Mark each header as read */
4054         do_headers_action (window, headers_action_mark_as_read, NULL);
4055 }
4056
4057 void
4058 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4059                                      ModestWindow *window)
4060 {
4061         g_return_if_fail (MODEST_IS_WINDOW(window));
4062
4063         /* Mark each header as read */
4064         do_headers_action (window, headers_action_mark_as_unread, NULL);
4065 }
4066
4067 void
4068 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4069                                   GtkRadioAction *selected,
4070                                   ModestWindow *window)
4071 {
4072         gint value;
4073
4074         value = gtk_radio_action_get_current_value (selected);
4075         if (MODEST_IS_WINDOW (window)) {
4076                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4077         }
4078 }
4079
4080 void
4081 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4082                                                GtkRadioAction *selected,
4083                                                ModestWindow *window)
4084 {
4085         TnyHeaderFlags flags;
4086         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4087
4088         flags = gtk_radio_action_get_current_value (selected);
4089         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4090 }
4091
4092 void
4093 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4094                                                   GtkRadioAction *selected,
4095                                                   ModestWindow *window)
4096 {
4097         gint file_format;
4098
4099         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4100
4101         file_format = gtk_radio_action_get_current_value (selected);
4102         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4103 }
4104
4105
4106 void
4107 modest_ui_actions_on_zoom_plus (GtkAction *action,
4108                                 ModestWindow *window)
4109 {
4110         g_return_if_fail (MODEST_IS_WINDOW (window));
4111
4112         modest_window_zoom_plus (MODEST_WINDOW (window));
4113 }
4114
4115 void
4116 modest_ui_actions_on_zoom_minus (GtkAction *action,
4117                                  ModestWindow *window)
4118 {
4119         g_return_if_fail (MODEST_IS_WINDOW (window));
4120
4121         modest_window_zoom_minus (MODEST_WINDOW (window));
4122 }
4123
4124 void
4125 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4126                                            ModestWindow *window)
4127 {
4128         ModestWindowMgr *mgr;
4129         gboolean fullscreen, active;
4130         g_return_if_fail (MODEST_IS_WINDOW (window));
4131
4132         mgr = modest_runtime_get_window_mgr ();
4133
4134         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4135         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4136
4137         if (active != fullscreen) {
4138                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4139 #ifndef MODEST_TOOLKIT_HILDON2
4140                 gtk_window_present (GTK_WINDOW (window));
4141 #endif
4142         }
4143 }
4144
4145 void
4146 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4147                                         ModestWindow *window)
4148 {
4149         ModestWindowMgr *mgr;
4150         gboolean fullscreen;
4151
4152         g_return_if_fail (MODEST_IS_WINDOW (window));
4153
4154         mgr = modest_runtime_get_window_mgr ();
4155         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4156         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4157
4158 #ifndef MODEST_TOOLKIT_HILDON2
4159         gtk_window_present (GTK_WINDOW (window));
4160 #endif
4161 }
4162
4163 /*
4164  * Used by modest_ui_actions_on_details to call do_headers_action
4165  */
4166 static void
4167 headers_action_show_details (TnyHeader *header,
4168                              ModestWindow *window,
4169                              gpointer user_data)
4170
4171 {
4172         gboolean async_retrieval;
4173         TnyMsg *msg = NULL;
4174
4175         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4176                 async_retrieval = TRUE;
4177                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4178         } else {
4179                 async_retrieval = FALSE;
4180         }
4181         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4182         if (msg)
4183                 g_object_unref (msg);
4184 }
4185
4186 /*
4187  * Show the header details in a ModestDetailsDialog widget
4188  */
4189 void
4190 modest_ui_actions_on_details (GtkAction *action,
4191                               ModestWindow *win)
4192 {
4193         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4194                 TnyMsg *msg;
4195                 TnyHeader *header;
4196
4197                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4198                 if (!msg)
4199                         return;
4200
4201                 header = tny_msg_get_header (msg);
4202                 if (header) {
4203                         headers_action_show_details (header, win, NULL);
4204                         g_object_unref (header);
4205                 }
4206                 g_object_unref (msg);
4207 #ifndef MODEST_TOOLKIT_HILDON2
4208         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4209                 GtkWidget *folder_view, *header_view;
4210
4211                 /* Check which widget has the focus */
4212                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4213                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4214                 if (gtk_widget_is_focus (folder_view)) {
4215                         TnyFolderStore *folder_store
4216                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4217                         if (!folder_store) {
4218                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4219                                 return;
4220                         }
4221                         /* Show only when it's a folder */
4222                         /* This function should not be called for account items,
4223                          * because we dim the menu item for them. */
4224                         if (TNY_IS_FOLDER (folder_store)) {
4225                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4226                                                                            TNY_FOLDER (folder_store));
4227                         }
4228
4229                         g_object_unref (folder_store);
4230
4231                 } else {
4232                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4233                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4234                         /* Show details of each header */
4235                         do_headers_action (win, headers_action_show_details, header_view);
4236                 }
4237 #else
4238         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4239                 TnyFolder *folder;
4240                 GtkWidget *header_view;
4241
4242                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4243                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4244                 if (folder) {
4245                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4246                                                                    folder);
4247                         g_object_unref (folder);
4248                 }
4249 #endif
4250         }
4251 }
4252
4253 void
4254 modest_ui_actions_on_limit_error (GtkAction *action,
4255                                   ModestWindow *win)
4256 {
4257         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4258
4259         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4260
4261 }
4262
4263 void
4264 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4265                                      ModestMsgEditWindow *window)
4266 {
4267         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4268
4269         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4270 }
4271
4272 void
4273 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4274                                       ModestMsgEditWindow *window)
4275 {
4276         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4277
4278         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4279 }
4280
4281 #ifndef MODEST_TOOLKIT_HILDON2
4282 void
4283 modest_ui_actions_toggle_folders_view (GtkAction *action,
4284                                        ModestMainWindow *main_window)
4285 {
4286         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4287
4288         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4289                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4290         else
4291                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4292 }
4293 #endif
4294
4295 void
4296 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4297                                      ModestWindow *window)
4298 {
4299         gboolean active, fullscreen = FALSE;
4300         ModestWindowMgr *mgr;
4301
4302         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4303
4304         /* Check if we want to toggle the toolbar view in fullscreen
4305            or normal mode */
4306         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4307                      "ViewShowToolbarFullScreen")) {
4308                 fullscreen = TRUE;
4309         }
4310
4311         /* Toggle toolbar */
4312         mgr = modest_runtime_get_window_mgr ();
4313         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4314 }
4315
4316 void
4317 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4318                                            ModestMsgEditWindow *window)
4319 {
4320         modest_msg_edit_window_select_font (window);
4321 }
4322
4323
4324 void
4325 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4326                                                   const gchar *display_name,
4327                                                   GtkWindow *window)
4328 {
4329         /* don't update the display name if it was already set;
4330          * updating the display name apparently is expensive */
4331         const gchar* old_name = gtk_window_get_title (window);
4332
4333         if (display_name == NULL)
4334                 display_name = " ";
4335
4336         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4337                 return; /* don't do anything */
4338
4339         /* This is usually used to change the title of the main window, which
4340          * is the one that holds the folder view. Note that this change can
4341          * happen even when the widget doesn't have the focus. */
4342         gtk_window_set_title (window, display_name);
4343
4344 }
4345
4346 void
4347 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4348 {
4349         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4350         modest_msg_edit_window_select_contacts (window);
4351 }
4352
4353 void
4354 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4355 {
4356         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4357         modest_msg_edit_window_check_names (window, FALSE);
4358 }
4359
4360 #ifndef MODEST_TOOLKIT_HILDON2
4361 /*
4362  * This function is used to track changes in the selection of the
4363  * folder view that is inside the "move to" dialog to enable/disable
4364  * the OK button because we do not want the user to select a disallowed
4365  * destination for a folder.
4366  * The user also not desired to be able to use NEW button on items where
4367  * folder creation is not possibel.
4368  */
4369 static void
4370 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4371                                             TnyFolderStore *folder_store,
4372                                             gboolean selected,
4373                                             gpointer user_data)
4374 {
4375         GtkWidget *dialog = NULL;
4376         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4377         gboolean moving_folder = FALSE;
4378         gboolean is_local_account = TRUE;
4379         GtkWidget *folder_view = NULL;
4380         ModestTnyFolderRules rules;
4381
4382         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4383
4384         if (!selected)
4385                 return;
4386
4387         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4388         if (!dialog)
4389                 return;
4390
4391         /* check if folder_store is an remote account */
4392         if (TNY_IS_ACCOUNT (folder_store)) {
4393                 TnyAccount *local_account = NULL;
4394                 TnyAccount *mmc_account = NULL;
4395                 ModestTnyAccountStore *account_store = NULL;
4396
4397                 account_store = modest_runtime_get_account_store ();
4398                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4399                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4400
4401                 if ((gpointer) local_account != (gpointer) folder_store &&
4402                     (gpointer) mmc_account != (gpointer) folder_store) {
4403                         ModestProtocolType proto;
4404                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4405                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4406                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4407                         }
4408                         is_local_account = FALSE;
4409                         /* New button should be dimmed on remote
4410                            POP account root */
4411                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4412                                                                                          proto,
4413                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4414                 }
4415                 g_object_unref (local_account);
4416
4417                 /* It could not exist */
4418                 if (mmc_account)
4419                         g_object_unref (mmc_account);
4420         }
4421
4422         /* Check the target folder rules */
4423         if (TNY_IS_FOLDER (folder_store)) {
4424                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4425                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4426                         ok_sensitive = FALSE;
4427                         new_sensitive = FALSE;
4428                         goto end;
4429                 }
4430         }
4431
4432         /* Check if we're moving a folder */
4433         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4434                 /* Get the widgets */
4435                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4436                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4437                 if (gtk_widget_is_focus (folder_view))
4438                         moving_folder = TRUE;
4439         }
4440
4441         if (moving_folder) {
4442                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4443
4444                 /* Get the folder to move */
4445                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4446
4447                 /* Check that we're not moving to the same folder */
4448                 if (TNY_IS_FOLDER (moved_folder)) {
4449                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4450                         if (parent == folder_store)
4451                                 ok_sensitive = FALSE;
4452                         g_object_unref (parent);
4453                 }
4454
4455                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4456                         /* Do not allow to move to an account unless it's the
4457                            local folders account */
4458                         if (!is_local_account)
4459                                 ok_sensitive = FALSE;
4460                 }
4461
4462                 if (ok_sensitive && (moved_folder == folder_store)) {
4463                         /* Do not allow to move to itself */
4464                         ok_sensitive = FALSE;
4465                 }
4466                 g_object_unref (moved_folder);
4467         } else {
4468                 TnyFolder *src_folder = NULL;
4469
4470                 /* Moving a message */
4471                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4472
4473                         TnyHeader *header = NULL;
4474                         header = modest_msg_view_window_get_header
4475                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4476                         if (!TNY_IS_HEADER(header))
4477                                 g_warning ("%s: could not get source header", __FUNCTION__);
4478                         else
4479                                 src_folder = tny_header_get_folder (header);
4480
4481                         if (header)
4482                                 g_object_unref (header);
4483                 } else {
4484                         src_folder =
4485                                 TNY_FOLDER (modest_folder_view_get_selected
4486                                             (MODEST_FOLDER_VIEW (folder_view)));
4487                 }
4488
4489                 if (TNY_IS_FOLDER(src_folder)) {
4490                         /* Do not allow to move the msg to the same folder */
4491                         /* Do not allow to move the msg to an account */
4492                         if ((gpointer) src_folder == (gpointer) folder_store ||
4493                             TNY_IS_ACCOUNT (folder_store))
4494                                 ok_sensitive = FALSE;
4495                         g_object_unref (src_folder);
4496                 } else
4497                         g_warning ("%s: could not get source folder", __FUNCTION__);
4498         }
4499
4500  end:
4501         /* Set sensitivity of the OK and NEW button */
4502         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
4503         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
4504 }
4505 #endif
4506
4507 static void
4508 on_move_to_dialog_response (GtkDialog *dialog,
4509                             gint       response,
4510                             gpointer   user_data)
4511 {
4512         GtkWidget *parent_win;
4513         MoveToInfo *helper = NULL;
4514         ModestFolderView *folder_view;
4515         gboolean unset_edit_mode = FALSE;
4516
4517         helper = (MoveToInfo *) user_data;
4518
4519         parent_win = (GtkWidget *) helper->win;
4520         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4521                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4522         switch (response) {
4523                 TnyFolderStore *dst_folder;
4524                 TnyFolderStore *selected;
4525
4526         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4527                 selected = modest_folder_view_get_selected (folder_view);
4528                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
4529                 g_object_unref (selected);
4530                 return;
4531         case GTK_RESPONSE_NONE:
4532         case GTK_RESPONSE_CANCEL:
4533         case GTK_RESPONSE_DELETE_EVENT:
4534                 break;
4535         case GTK_RESPONSE_OK:
4536                 dst_folder = modest_folder_view_get_selected (folder_view);
4537
4538                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4539                         /* Clean list to move used for filtering */
4540                         modest_folder_view_set_list_to_move (folder_view, NULL);
4541
4542                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4543                                                                     dst_folder,
4544                                                                     helper->list,
4545                                                                     GTK_WINDOW (parent_win));
4546                 } else {
4547                         /* if the user selected a root folder
4548                            (account) then do not perform any action */
4549                         if (TNY_IS_ACCOUNT (dst_folder)) {
4550                                 g_signal_stop_emission_by_name (dialog, "response");
4551                                 return;
4552                         }
4553
4554                         /* Clean list to move used for filtering */
4555                         modest_folder_view_set_list_to_move (folder_view, NULL);
4556
4557                         /* Moving from headers window in edit mode */
4558                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4559                                                              dst_folder,
4560                                                              MODEST_WINDOW (parent_win));
4561                 }
4562
4563                 if (dst_folder)
4564                         g_object_unref (dst_folder);
4565
4566                 unset_edit_mode = TRUE;
4567                 break;
4568         default:
4569                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4570         }
4571
4572         /* Free the helper and exit */
4573         if (helper->list)
4574                 g_object_unref (helper->list);
4575         if (unset_edit_mode) {
4576 #ifdef MODEST_TOOLKIT_HILDON2
4577                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
4578 #endif
4579         }
4580         g_slice_free (MoveToInfo, helper);
4581         gtk_widget_destroy (GTK_WIDGET (dialog));
4582 }
4583
4584 static GtkWidget*
4585 create_move_to_dialog (GtkWindow *win,
4586                        GtkWidget *folder_view,
4587                        TnyList *list_to_move)
4588 {
4589         GtkWidget *dialog, *tree_view = NULL;
4590
4591         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
4592
4593
4594         /* It could happen that we're trying to move a message from a
4595            window (msg window for example) after the main window was
4596            closed, so we can not just get the model of the folder
4597            view */
4598         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4599                 const gchar *visible_id = NULL;
4600
4601                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4602                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4603                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4604                                                MODEST_FOLDER_VIEW(tree_view));
4605
4606                 visible_id =
4607                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4608
4609                 /* Show the same account than the one that is shown in the main window */
4610                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
4611                                                                              visible_id);
4612         } else {
4613                 const gchar *active_account_name = NULL;
4614                 ModestAccountMgr *mgr = NULL;
4615                 ModestAccountSettings *settings = NULL;
4616                 ModestServerAccountSettings *store_settings = NULL;
4617
4618                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4619                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4620                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
4621                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
4622
4623                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4624                 mgr = modest_runtime_get_account_mgr ();
4625                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4626
4627                 if (settings) {
4628                         const gchar *store_account_name;
4629                         store_settings = modest_account_settings_get_store_settings (settings);
4630                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4631
4632                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
4633                                                                                      store_account_name);
4634                         g_object_unref (store_settings);
4635                         g_object_unref (settings);
4636                 }
4637         }
4638
4639         /* we keep a pointer to the embedded folder view, so we can
4640          *   retrieve it with get_folder_view_from_move_to_dialog (see
4641          *   above) later (needed for focus handling)
4642          */
4643         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
4644
4645         /* Hide special folders */
4646 #ifndef MODEST_TOOLKIT_HILDON2
4647         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
4648 #endif
4649         if (list_to_move)
4650                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
4651 #ifndef MODEST_TOOLKIT_HILDON2
4652         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4653 #endif
4654
4655         gtk_widget_show (GTK_WIDGET (tree_view));
4656
4657         return dialog;
4658 }
4659
4660 /*
4661  * Shows a confirmation dialog to the user when we're moving messages
4662  * from a remote server to the local storage. Returns the dialog
4663  * response. If it's other kind of movement then it always returns
4664  * GTK_RESPONSE_OK
4665  *
4666  * This one is used by the next functions:
4667  *      modest_ui_actions_on_paste                      - commented out
4668  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4669  */
4670 gint
4671 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4672                                              TnyFolder *dest_folder,
4673                                              gboolean delete,
4674                                              TnyList *headers)
4675 {
4676         gint response = GTK_RESPONSE_OK;
4677         TnyAccount *account = NULL;
4678         TnyFolder *src_folder = NULL;
4679         TnyIterator *iter = NULL;
4680         TnyHeader *header = NULL;
4681
4682         /* return with OK if the destination is a remote folder */
4683         if (modest_tny_folder_is_remote_folder (dest_folder))
4684                 return GTK_RESPONSE_OK;
4685
4686         /* Get source folder */
4687         iter = tny_list_create_iterator (headers);
4688         header = TNY_HEADER (tny_iterator_get_current (iter));
4689         if (header) {
4690                 src_folder = tny_header_get_folder (header);
4691                 g_object_unref (header);
4692         }
4693         g_object_unref (iter);
4694
4695         /* if no src_folder, message may be an attahcment */
4696         if (src_folder == NULL)
4697                 return GTK_RESPONSE_CANCEL;
4698
4699         /* If the source is a local or MMC folder */
4700         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4701                 g_object_unref (src_folder);
4702                 return GTK_RESPONSE_OK;
4703         }
4704
4705         /* Get the account */
4706         account = tny_folder_get_account (src_folder);
4707
4708         /* now if offline we ask the user */
4709         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4710                 response = GTK_RESPONSE_OK;
4711         else
4712                 response = GTK_RESPONSE_CANCEL;
4713
4714         /* Frees */
4715         g_object_unref (src_folder);
4716         g_object_unref (account);
4717
4718         return response;
4719 }
4720
4721 static void
4722 move_to_helper_destroyer (gpointer user_data)
4723 {
4724         MoveToHelper *helper = (MoveToHelper *) user_data;
4725
4726         /* Close the "Pasting" information banner */
4727         if (helper->banner) {
4728                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4729                 g_object_unref (helper->banner);
4730         }
4731         if (gtk_tree_row_reference_valid (helper->reference)) {
4732                 gtk_tree_row_reference_free (helper->reference);
4733                 helper->reference = NULL;
4734         }
4735         g_free (helper);
4736 }
4737
4738 static void
4739 move_to_cb (ModestMailOperation *mail_op,
4740             gpointer user_data)
4741 {
4742         MoveToHelper *helper = (MoveToHelper *) user_data;
4743         GObject *object = modest_mail_operation_get_source (mail_op);
4744
4745         /* Note that the operation could have failed, in that case do
4746            nothing */
4747         if (modest_mail_operation_get_status (mail_op) !=
4748             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4749                 goto frees;
4750
4751         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4752                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4753
4754                 if (!modest_msg_view_window_select_next_message (self) &&
4755                     !modest_msg_view_window_select_previous_message (self)) {
4756                         /* No more messages to view, so close this window */
4757                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4758                 }
4759 #ifndef MODEST_TOOLKIT_HILDON2
4760         } else if (MODEST_IS_MAIN_WINDOW (object) &&
4761                    gtk_tree_row_reference_valid (helper->reference)) {
4762                 GtkWidget *header_view;
4763                 GtkTreePath *path;
4764                 GtkTreeSelection *sel;
4765
4766                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4767                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4768                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4769                 path = gtk_tree_row_reference_get_path (helper->reference);
4770                 /* We need to unselect the previous one
4771                    because we could be copying instead of
4772                    moving */
4773                 gtk_tree_selection_unselect_all (sel);
4774                 gtk_tree_selection_select_path (sel, path);
4775                 gtk_tree_path_free (path);
4776 #endif
4777         }
4778         g_object_unref (object);
4779
4780  frees:
4781         /* Destroy the helper */
4782         move_to_helper_destroyer (helper);
4783 }
4784
4785 static void
4786 folder_move_to_cb (ModestMailOperation *mail_op,
4787                    TnyFolder *new_folder,
4788                    gpointer user_data)
4789 {
4790         GObject *object;
4791
4792         object = modest_mail_operation_get_source (mail_op);
4793 #ifndef MODEST_TOOLKIT_HILDON2
4794         if (MODEST_IS_MAIN_WINDOW (object)) {
4795                 GtkWidget *folder_view;
4796                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4797                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4798                 g_object_ref (folder_view);
4799                 g_object_unref (object);
4800                 move_to_cb (mail_op, user_data);
4801                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4802                 g_object_unref (folder_view);
4803         } else {
4804 #else
4805                 {
4806 #endif
4807                 move_to_cb (mail_op, user_data);
4808         }
4809 }
4810
4811 static void
4812 msgs_move_to_cb (ModestMailOperation *mail_op,
4813                  gpointer user_data)
4814 {
4815         move_to_cb (mail_op, user_data);
4816 }
4817
4818 void
4819 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4820                                              gpointer user_data)
4821 {
4822         GObject *win = NULL;
4823         const GError *error;
4824         TnyAccount *account = NULL;
4825
4826 #ifndef MODEST_TOOLKIT_HILDON2
4827         ModestWindow *main_window = NULL;
4828
4829         /* Disable next automatic folder selection */
4830         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4831                                                          FALSE); /* don't create */
4832
4833         /* Show notification dialog only if the main window exists */
4834         if (main_window) {
4835                 GtkWidget *folder_view = NULL;
4836
4837                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4838                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4839                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4840
4841                 if (user_data && TNY_IS_FOLDER (user_data)) {
4842                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
4843                                                           TNY_FOLDER (user_data), FALSE);
4844                 }
4845         }
4846 #endif
4847         win = modest_mail_operation_get_source (mail_op);
4848         error = modest_mail_operation_get_error (mail_op);
4849
4850         if (TNY_IS_FOLDER (user_data))
4851                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
4852         else if (TNY_IS_ACCOUNT (user_data))
4853                 account = g_object_ref (user_data);
4854
4855         /* If it's not a disk full error then show a generic error */
4856         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4857                                                              (GtkWidget *) win, (GError *) error,
4858                                                              account, NULL))
4859                 modest_platform_run_information_dialog ((GtkWindow *) win,
4860                                                         _("mail_in_ui_folder_move_target_error"),
4861                                                         FALSE);
4862         if (account)
4863                 g_object_unref (account);
4864         if (win)
4865                 g_object_unref (win);
4866 }
4867
4868 #ifndef MODEST_TOOLKIT_HILDON2
4869 static void
4870 open_msg_for_purge_cb (ModestMailOperation *mail_op,
4871                        TnyHeader *header,
4872                        gboolean canceled,
4873                        TnyMsg *msg,
4874                        GError *err,
4875                        gpointer user_data)
4876 {
4877         TnyList *parts;
4878         TnyIterator *iter;
4879         gint pending_purges = 0;
4880         gboolean some_purged = FALSE;
4881         ModestWindow *win = MODEST_WINDOW (user_data);
4882         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4883
4884         /* If there was any error */
4885         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4886                 modest_window_mgr_unregister_header (mgr, header);
4887                 return;
4888         }
4889
4890         /* Once the message has been retrieved for purging, we check if
4891          * it's all ok for purging */
4892
4893         parts = tny_simple_list_new ();
4894         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4895         iter = tny_list_create_iterator (parts);
4896
4897         while (!tny_iterator_is_done (iter)) {
4898                 TnyMimePart *part;
4899                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4900                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4901                         if (tny_mime_part_is_purged (part))
4902                                 some_purged = TRUE;
4903                         else
4904                                 pending_purges++;
4905                 }
4906
4907                 if (part)
4908                         g_object_unref (part);
4909
4910                 tny_iterator_next (iter);
4911         }
4912         g_object_unref (iter);
4913
4914
4915         if (pending_purges>0) {
4916                 gint response;
4917                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4918
4919                 if (response == GTK_RESPONSE_OK) {
4920                         GtkWidget *info;
4921                         info =
4922                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
4923                         iter = tny_list_create_iterator (parts);
4924                         while (!tny_iterator_is_done (iter)) {
4925                                 TnyMimePart *part;
4926
4927                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4928                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4929                                         tny_mime_part_set_purged (part);
4930
4931                                 if (part)
4932                                         g_object_unref (part);
4933
4934                                 tny_iterator_next (iter);
4935                         }
4936                         g_object_unref (iter);
4937
4938                         tny_msg_rewrite_cache (msg);
4939
4940                         gtk_widget_destroy (info);
4941                 }
4942         }
4943
4944         modest_window_mgr_unregister_header (mgr, header);
4945
4946         g_object_unref (parts);
4947 }
4948
4949 static void
4950 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4951                                                      ModestMainWindow *win)
4952 {
4953         GtkWidget *header_view;
4954         TnyList *header_list;
4955         TnyHeader *header;
4956         TnyHeaderFlags flags;
4957         ModestWindow *msg_view_window =  NULL;
4958         gboolean found;
4959
4960         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4961
4962         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4963                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4964
4965         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4966         if (!header_list) {
4967                 g_warning ("%s: no header selected", __FUNCTION__);
4968                 return;
4969         }
4970
4971         if (tny_list_get_length (header_list) == 1) {
4972                 TnyIterator *iter = tny_list_create_iterator (header_list);
4973                 header = TNY_HEADER (tny_iterator_get_current (iter));
4974                 g_object_unref (iter);
4975         } else
4976                 return;
4977
4978         if (!header || !TNY_IS_HEADER(header)) {
4979                 g_warning ("%s: header is not valid", __FUNCTION__);
4980                 return;
4981         }
4982
4983         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4984                                                           header, &msg_view_window);
4985         flags = tny_header_get_flags (header);
4986         if (!(flags & TNY_HEADER_FLAG_CACHED))
4987                 return;
4988         if (found) {
4989                 if (msg_view_window != NULL)
4990                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4991                 else {
4992                         /* do nothing; uid was registered before, so window is probably on it's way */
4993                         g_debug ("header %p has already been registered", header);
4994                 }
4995         } else {
4996                 ModestMailOperation *mail_op = NULL;
4997                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4998                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4999                                                                          modest_ui_actions_disk_operations_error_handler,
5000                                                                          NULL, NULL);
5001                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5002                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5003
5004                 g_object_unref (mail_op);
5005         }
5006         if (header)
5007                 g_object_unref (header);
5008         if (header_list)
5009                 g_object_unref (header_list);
5010 }
5011 #endif
5012
5013 /*
5014  * Checks if we need a connection to do the transfer and if the user
5015  * wants to connect to complete it
5016  */
5017 static void
5018 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5019                                        TnyFolderStore *src_folder,
5020                                        TnyList *headers,
5021                                        TnyFolder *dst_folder,
5022                                        gboolean delete_originals,
5023                                        gboolean *need_connection,
5024                                        gboolean *do_xfer)
5025 {
5026         TnyAccount *src_account;
5027         gint uncached_msgs = 0;
5028
5029         /* We don't need any further check if
5030          *
5031          * 1- the source folder is local OR
5032          * 2- the device is already online
5033          */
5034         if (!modest_tny_folder_store_is_remote (src_folder) ||
5035             tny_device_is_online (modest_runtime_get_device())) {
5036                 *need_connection = FALSE;
5037                 *do_xfer = TRUE;
5038                 return;
5039         }
5040
5041         /* We must ask for a connection when
5042          *
5043          *   - the message(s) is not already cached   OR
5044          *   - the message(s) is cached but the leave_on_server setting
5045          * is FALSE (because we need to sync the source folder to
5046          * delete the message from the server (for IMAP we could do it
5047          * offline, it'll take place the next time we get a
5048          * connection)
5049          */
5050         uncached_msgs = header_list_count_uncached_msgs (headers);
5051         src_account = get_account_from_folder_store (src_folder);
5052         if (uncached_msgs > 0) {
5053                 guint num_headers;
5054                 const gchar *msg;
5055
5056                 *need_connection = TRUE;
5057                 num_headers = tny_list_get_length (headers);
5058                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5059
5060                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5061                     GTK_RESPONSE_CANCEL) {
5062                         *do_xfer = FALSE;
5063                 } else {
5064                         *do_xfer = TRUE;
5065                 }
5066         } else {
5067                 /* The transfer is possible and the user wants to */
5068                 *do_xfer = TRUE;
5069
5070                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5071                         const gchar *account_name;
5072                         gboolean leave_on_server;
5073
5074                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5075                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5076                                                                                   account_name);
5077
5078                         if (leave_on_server == TRUE) {
5079                                 *need_connection = FALSE;
5080                         } else {
5081                                 *need_connection = TRUE;
5082                         }
5083                 } else {
5084                         *need_connection = FALSE;
5085                 }
5086         }
5087
5088         /* Frees */
5089         g_object_unref (src_account);
5090 }
5091
5092 static void
5093 xfer_messages_error_handler (ModestMailOperation *mail_op,
5094                              gpointer user_data)
5095 {
5096         GObject *win;
5097         const GError *error;
5098         TnyAccount *account;
5099
5100         win = modest_mail_operation_get_source (mail_op);
5101         error = modest_mail_operation_get_error (mail_op);
5102
5103         /* We cannot get the account from the mail op as that is the
5104            source account and for checking memory full conditions we
5105            need the destination one */
5106         account = TNY_ACCOUNT (user_data);
5107
5108         if (error &&
5109             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5110                                                              (GtkWidget *) win, (GError*) error,
5111                                                              account, _KR("cerm_memory_card_full"))) {
5112                 modest_platform_run_information_dialog ((GtkWindow *) win,
5113                                                         _("mail_in_ui_folder_move_target_error"),
5114                                                         FALSE);
5115         }
5116         if (win)
5117                 g_object_unref (win);
5118 }
5119
5120 typedef struct {
5121         TnyFolderStore *dst_folder;
5122         TnyList *headers;
5123 } XferMsgsHelper;
5124
5125 /**
5126  * Utility function that transfer messages from both the main window
5127  * and the msg view window when using the "Move to" dialog
5128  */
5129 static void
5130 xfer_messages_performer  (gboolean canceled,
5131                           GError *err,
5132                           GtkWindow *parent_window,
5133                           TnyAccount *account,
5134                           gpointer user_data)
5135 {
5136         ModestWindow *win = MODEST_WINDOW (parent_window);
5137         TnyAccount *dst_account = NULL;
5138         gboolean dst_forbids_message_add = FALSE;
5139         XferMsgsHelper *helper;
5140         MoveToHelper *movehelper;
5141         ModestMailOperation *mail_op;
5142
5143         helper = (XferMsgsHelper *) user_data;
5144
5145         if (canceled || err) {
5146                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5147                                                                      (GtkWidget *) parent_window, err,
5148                                                                      account, NULL)) {
5149                         /* Show the proper error message */
5150                         modest_ui_actions_on_account_connection_error (parent_window, account);
5151                 }
5152                 goto end;
5153         }
5154
5155         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5156
5157         /* tinymail will return NULL for local folders it seems */
5158         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5159                                                                                   modest_tny_account_get_protocol_type (dst_account),
5160                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5161
5162         if (dst_forbids_message_add) {
5163                 modest_platform_information_banner (GTK_WIDGET (win),
5164                                                     NULL,
5165                                                     ngettext("mail_in_ui_folder_move_target_error",
5166                                                              "mail_in_ui_folder_move_targets_error",
5167                                                              tny_list_get_length (helper->headers)));
5168                 goto end;
5169         }
5170
5171         movehelper = g_new0 (MoveToHelper, 1);
5172
5173 #ifndef MODEST_TOOLKIT_HILDON2
5174         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5175                                                                _CS("ckct_nw_pasting"));
5176         if (movehelper->banner != NULL)  {
5177                 g_object_ref (movehelper->banner);
5178                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5179         }
5180
5181         if (MODEST_IS_MAIN_WINDOW (win)) {
5182                 GtkWidget *header_view =
5183                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5184                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5185                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5186         }
5187 #endif
5188
5189         /* Perform the mail operation */
5190         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5191                                                                  xfer_messages_error_handler,
5192                                                                  g_object_ref (dst_account),
5193                                                                  g_object_unref);
5194         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5195                                          mail_op);
5196
5197         modest_mail_operation_xfer_msgs (mail_op,
5198                                          helper->headers,
5199                                          TNY_FOLDER (helper->dst_folder),
5200                                          TRUE,
5201                                          msgs_move_to_cb,
5202                                          movehelper);
5203
5204         g_object_unref (G_OBJECT (mail_op));
5205  end:
5206         if (dst_account)
5207                 g_object_unref (dst_account);
5208         g_object_unref (helper->dst_folder);
5209         g_object_unref (helper->headers);
5210         g_slice_free (XferMsgsHelper, helper);
5211 }
5212
5213 typedef struct {
5214         TnyFolder *src_folder;
5215         TnyFolderStore *dst_folder;
5216         gboolean delete_original;
5217         GtkWidget *folder_view;
5218 } MoveFolderInfo;
5219
5220 static void
5221 on_move_folder_cb (gboolean canceled,
5222                    GError *err,
5223                    GtkWindow *parent_window,
5224                    TnyAccount *account,
5225                    gpointer user_data)
5226 {
5227         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5228         GtkTreeSelection *sel;
5229         ModestMailOperation *mail_op = NULL;
5230
5231         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5232                 /* Note that the connection process can fail due to
5233                    memory low conditions as it can not successfully
5234                    store the summary */
5235                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5236                                                                      (GtkWidget*) parent_window, err,
5237                                                                      account, NULL))
5238                         g_debug ("Error connecting when trying to move a folder");
5239
5240                 g_object_unref (G_OBJECT (info->src_folder));
5241                 g_object_unref (G_OBJECT (info->dst_folder));
5242                 g_free (info);
5243                 return;
5244         }
5245
5246         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5247 #ifndef MODEST_TOOLKIT_HILDON2
5248         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5249                         _CS("ckct_nw_pasting"));
5250         if (helper->banner != NULL)  {
5251                 g_object_ref (helper->banner);
5252                 gtk_widget_show (GTK_WIDGET(helper->banner));
5253         }
5254 #endif
5255         /* Clean folder on header view before moving it */
5256         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5257         gtk_tree_selection_unselect_all (sel);
5258
5259         /* Let gtk events run. We need that the folder
5260            view frees its reference to the source
5261            folder *before* issuing the mail operation
5262            so we need the signal handler of selection
5263            changed to happen before the mail
5264            operation
5265         while (gtk_events_pending ())
5266                 gtk_main_iteration ();   */
5267
5268         mail_op =
5269                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5270                                                                modest_ui_actions_move_folder_error_handler,
5271                                                                g_object_ref (info->dst_folder), g_object_unref);
5272         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5273                                          mail_op);
5274
5275 #ifndef MODEST_TOOLKIT_HILDON2
5276         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5277                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5278                                                   TNY_FOLDER (info->dst_folder), TRUE);
5279         }
5280 #endif
5281         modest_mail_operation_xfer_folder (mail_op,
5282                         TNY_FOLDER (info->src_folder),
5283                         info->dst_folder,
5284                         info->delete_original,
5285                         folder_move_to_cb,
5286                         helper);
5287         g_object_unref (G_OBJECT (info->src_folder));
5288
5289         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5290         /* } */
5291
5292         /* Unref mail operation */
5293         g_object_unref (G_OBJECT (mail_op));
5294         g_object_unref (G_OBJECT (info->dst_folder));
5295         g_free (user_data);
5296 }
5297
5298 static TnyAccount *
5299 get_account_from_folder_store (TnyFolderStore *folder_store)
5300 {
5301         if (TNY_IS_ACCOUNT (folder_store))
5302                 return g_object_ref (folder_store);
5303         else
5304                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5305 }
5306
5307 #ifndef MODEST_TOOLKIT_HILDON2
5308 /*
5309  * UI handler for the "Move to" action when invoked from the
5310  * ModestMainWindow
5311  */
5312 static void
5313 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5314                                           GtkWidget *folder_view,
5315                                           TnyFolderStore *dst_folder,
5316                                           ModestMainWindow *win)
5317 {
5318         ModestHeaderView *header_view = NULL;
5319         TnyFolderStore *src_folder = NULL;
5320
5321         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5322
5323         /* Get the source folder */
5324         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5325
5326         /* Get header view */
5327         header_view = (ModestHeaderView *)
5328                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5329
5330         /* Get folder or messages to transfer */
5331         if (gtk_widget_is_focus (folder_view)) {
5332                 gboolean do_xfer = TRUE;
5333
5334                 /* Allow only to transfer folders to the local root folder */
5335                 if (TNY_IS_ACCOUNT (dst_folder) &&
5336                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5337                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5338                         do_xfer = FALSE;
5339                 } else if (!TNY_IS_FOLDER (src_folder)) {
5340                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5341                         do_xfer = FALSE;
5342                 }
5343
5344                 if (do_xfer) {
5345                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5346                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5347
5348                         info->src_folder = g_object_ref (src_folder);
5349                         info->dst_folder = g_object_ref (dst_folder);
5350                         info->delete_original = TRUE;
5351                         info->folder_view = folder_view;
5352
5353                         connect_info->callback = on_move_folder_cb;
5354                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5355                         connect_info->data = info;
5356
5357                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5358                                                                    TNY_FOLDER_STORE (src_folder),
5359                                                                    connect_info);
5360                 }
5361         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5362                 TnyList *headers;
5363
5364                 headers = modest_header_view_get_selected_headers(header_view);
5365
5366                 /* Transfer the messages */
5367                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5368                                                             headers, TNY_FOLDER (dst_folder));
5369
5370                 g_object_unref (headers);
5371         }
5372
5373         /* Frees */
5374         g_object_unref (src_folder);
5375 }
5376 #endif
5377
5378 #ifdef MODEST_TOOLKIT_HILDON2
5379 /*
5380  * UI handler for the "Move to" action when invoked from the
5381  * ModestFolderWindow
5382  */
5383 static void
5384 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5385                                             TnyFolderStore *dst_folder,
5386                                             TnyList *selection,
5387                                             GtkWindow *win)
5388 {
5389         TnyFolderStore *src_folder = NULL;
5390         TnyIterator *iterator;
5391
5392         if (tny_list_get_length (selection) != 1)
5393                 return;
5394
5395         iterator = tny_list_create_iterator (selection);
5396         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5397         g_object_unref (iterator);
5398
5399
5400         gboolean do_xfer = TRUE;
5401
5402         /* Allow only to transfer folders to the local root folder */
5403         if (TNY_IS_ACCOUNT (dst_folder) &&
5404             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5405             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5406                 do_xfer = FALSE;
5407                 /* Show an error */
5408                 modest_platform_run_information_dialog (win,
5409                                                         _("mail_in_ui_folder_move_target_error"),
5410                                                         FALSE);
5411         } else if (!TNY_IS_FOLDER (src_folder)) {
5412                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5413                 do_xfer = FALSE;
5414         }
5415
5416         if (do_xfer) {
5417                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5418                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5419
5420                 info->src_folder = g_object_ref (src_folder);
5421                 info->dst_folder = g_object_ref (dst_folder);
5422                 info->delete_original = TRUE;
5423                 info->folder_view = folder_view;
5424
5425                 connect_info->callback = on_move_folder_cb;
5426                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5427                 connect_info->data = info;
5428
5429                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5430                                                            TNY_FOLDER_STORE (src_folder),
5431                                                            connect_info);
5432         }
5433
5434         /* Frees */
5435         g_object_unref (src_folder);
5436 }
5437 #endif
5438
5439
5440 void
5441 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5442                                             TnyFolder *src_folder,
5443                                             TnyList *headers,
5444                                             TnyFolder *dst_folder)
5445 {
5446         gboolean need_connection = TRUE;
5447         gboolean do_xfer = TRUE;
5448         XferMsgsHelper *helper;
5449
5450         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5451         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5452         g_return_if_fail (TNY_IS_LIST (headers));
5453
5454         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5455                                                headers, TNY_FOLDER (dst_folder),
5456                                                TRUE, &need_connection,
5457                                                &do_xfer);
5458
5459         /* If we don't want to transfer just return */
5460         if (!do_xfer)
5461                 return;
5462
5463         /* Create the helper */
5464         helper = g_slice_new (XferMsgsHelper);
5465         helper->dst_folder = g_object_ref (dst_folder);
5466         helper->headers = g_object_ref (headers);
5467
5468         if (need_connection) {
5469                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5470                 connect_info->callback = xfer_messages_performer;
5471                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5472                 connect_info->data = helper;
5473
5474                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5475                                                            TNY_FOLDER_STORE (src_folder),
5476                                                            connect_info);
5477         } else {
5478                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5479                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5480                                          src_account, helper);
5481                 g_object_unref (src_account);
5482         }
5483 }
5484
5485 /*
5486  * UI handler for the "Move to" action when invoked from the
5487  * ModestMsgViewWindow
5488  */
5489 static void
5490 modest_ui_actions_on_window_move_to (GtkAction *action,
5491                                      TnyList *headers,
5492                                      TnyFolderStore *dst_folder,
5493                                      ModestWindow *win)
5494 {
5495         TnyFolder *src_folder = NULL;
5496
5497         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5498
5499         if (headers) {
5500                 TnyHeader *header = NULL;
5501                 TnyIterator *iter;
5502
5503                 iter = tny_list_create_iterator (headers);
5504                 header = (TnyHeader *) tny_iterator_get_current (iter);
5505                 src_folder = tny_header_get_folder (header);
5506
5507                 /* Transfer the messages */
5508                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
5509                                                             headers,
5510                                                             TNY_FOLDER (dst_folder));
5511
5512                 /* Frees */
5513                 g_object_unref (header);
5514                 g_object_unref (iter);
5515                 g_object_unref (src_folder);
5516         }
5517 }
5518
5519 void
5520 modest_ui_actions_on_move_to (GtkAction *action,
5521                               ModestWindow *win)
5522 {
5523         modest_ui_actions_on_edit_mode_move_to (win);
5524 }
5525
5526 gboolean
5527 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5528 {
5529         GtkWidget *dialog = NULL;
5530         MoveToInfo *helper = NULL;
5531         TnyList *list_to_move;
5532
5533         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5534
5535 #ifndef MODEST_TOOLKIT_HILDON2
5536         /* Get the main window if exists */
5537         ModestMainWindow *main_window;
5538         if (MODEST_IS_MAIN_WINDOW (win))
5539                 main_window = MODEST_MAIN_WINDOW (win);
5540         else
5541                 main_window =
5542                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5543                                                                                FALSE)); /* don't create */
5544 #endif
5545
5546         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5547
5548         if (!list_to_move)
5549                 return FALSE;
5550
5551         if (tny_list_get_length (list_to_move) < 1) {
5552                 g_object_unref (list_to_move);
5553                 return FALSE;
5554         }
5555
5556         /* Create and run the dialog */
5557         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
5558         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5559                                      GTK_WINDOW (dialog),
5560                                      (GtkWindow *) win);
5561
5562         /* Create helper */
5563         helper = g_slice_new0 (MoveToInfo);
5564         helper->list = list_to_move;
5565         helper->win = win;
5566
5567         /* Listen to response signal */
5568         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5569
5570         /* Show the dialog */
5571         gtk_widget_show (dialog);
5572
5573         return FALSE;
5574 }
5575
5576 /*
5577  * Calls #HeadersFunc for each header already selected in the main
5578  * window or the message currently being shown in the msg view window
5579  */
5580 static void
5581 do_headers_action (ModestWindow *win,
5582                    HeadersFunc func,
5583                    gpointer user_data)
5584 {
5585         TnyList *headers_list = NULL;
5586         TnyIterator *iter = NULL;
5587         TnyHeader *header = NULL;
5588         TnyFolder *folder = NULL;
5589
5590         /* Get headers */
5591         headers_list = get_selected_headers (win);
5592         if (!headers_list)
5593                 return;
5594
5595         /* Get the folder */
5596         iter = tny_list_create_iterator (headers_list);
5597         header = TNY_HEADER (tny_iterator_get_current (iter));
5598         if (header) {
5599                 folder = tny_header_get_folder (header);
5600                 g_object_unref (header);
5601         }
5602
5603         /* Call the function for each header */
5604         while (!tny_iterator_is_done (iter)) {
5605                 header = TNY_HEADER (tny_iterator_get_current (iter));
5606                 func (header, win, user_data);
5607                 g_object_unref (header);
5608                 tny_iterator_next (iter);
5609         }
5610
5611         /* Trick: do a poke status in order to speed up the signaling
5612            of observers */
5613         if (folder) {
5614                 tny_folder_poke_status (folder);
5615                 g_object_unref (folder);
5616         }
5617
5618         /* Frees */
5619         g_object_unref (iter);
5620         g_object_unref (headers_list);
5621 }
5622
5623 void
5624 modest_ui_actions_view_attachment (GtkAction *action,
5625                                    ModestWindow *window)
5626 {
5627         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5628                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5629         } else {
5630                 /* not supported window for this action */
5631                 g_return_if_reached ();
5632         }
5633 }
5634
5635 void
5636 modest_ui_actions_save_attachments (GtkAction *action,
5637                                     ModestWindow *window)
5638 {
5639         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5640
5641                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5642                         return;
5643
5644                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5645         } else {
5646                 /* not supported window for this action */
5647                 g_return_if_reached ();
5648         }
5649 }
5650
5651 void
5652 modest_ui_actions_remove_attachments (GtkAction *action,
5653                                       ModestWindow *window)
5654 {
5655 #ifndef MODEST_TOOLKIT_HILDON2
5656         if (MODEST_IS_MAIN_WINDOW (window)) {
5657                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5658         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5659 #else
5660         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5661 #endif
5662                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5663         } else {
5664                 /* not supported window for this action */
5665                 g_return_if_reached ();
5666         }
5667 }
5668
5669 void
5670 modest_ui_actions_on_settings (GtkAction *action,
5671                                ModestWindow *win)
5672 {
5673         GtkWidget *dialog;
5674
5675         dialog = modest_platform_get_global_settings_dialog ();
5676         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5677         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5678         gtk_widget_show_all (dialog);
5679
5680         gtk_dialog_run (GTK_DIALOG (dialog));
5681
5682         gtk_widget_destroy (dialog);
5683 }
5684
5685 void
5686 modest_ui_actions_on_help (GtkAction *action,
5687                            GtkWindow *win)
5688 {
5689         /* Help app is not available at all in fremantle */
5690 #ifndef MODEST_TOOLKIT_HILDON2
5691         const gchar *help_id;
5692
5693         g_return_if_fail (win && GTK_IS_WINDOW(win));
5694
5695         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5696
5697         if (help_id)
5698                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5699 #endif
5700 }
5701
5702 void
5703 modest_ui_actions_on_csm_help (GtkAction *action,
5704                                GtkWindow *win)
5705 {
5706         /* Help app is not available at all in fremantle */
5707 #ifndef MODEST_TOOLKIT_HILDON2
5708
5709         const gchar* help_id = NULL;
5710         GtkWidget *folder_view;
5711         TnyFolderStore *folder_store;
5712
5713         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5714
5715         /* Get selected folder */
5716         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5717                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5718         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5719
5720         /* Switch help_id */
5721         if (folder_store && TNY_IS_FOLDER (folder_store))
5722                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5723
5724         if (folder_store)
5725                 g_object_unref (folder_store);
5726
5727         if (help_id)
5728                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5729         else
5730                 modest_ui_actions_on_help (action, win);
5731 #endif
5732 }
5733
5734 static void
5735 retrieve_contents_cb (ModestMailOperation *mail_op,
5736                       TnyHeader *header,
5737                       gboolean canceled,
5738                       TnyMsg *msg,
5739                       GError *err,
5740                       gpointer user_data)
5741 {
5742         /* We only need this callback to show an error in case of
5743            memory low condition */
5744         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5745                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
5746         }
5747 }
5748
5749 static void
5750 retrieve_msg_contents_performer (gboolean canceled,
5751                                  GError *err,
5752                                  GtkWindow *parent_window,
5753                                  TnyAccount *account,
5754                                  gpointer user_data)
5755 {
5756         ModestMailOperation *mail_op;
5757         TnyList *headers = TNY_LIST (user_data);
5758
5759         if (err || canceled) {
5760                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5761                                                                 (GtkWidget *) parent_window, err,
5762                                                                 account, NULL);
5763                 goto out;
5764         }
5765
5766         /* Create mail operation */
5767         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5768                                                                  modest_ui_actions_disk_operations_error_handler,
5769                                                                  NULL, NULL);
5770         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5771         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5772
5773         /* Frees */
5774         g_object_unref (mail_op);
5775  out:
5776         g_object_unref (headers);
5777         g_object_unref (account);
5778 }
5779
5780 void
5781 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5782                                             ModestWindow *window)
5783 {
5784         TnyList *headers = NULL;
5785         TnyAccount *account = NULL;
5786         TnyIterator *iter = NULL;
5787         TnyHeader *header = NULL;
5788         TnyFolder *folder = NULL;
5789
5790         /* Get headers */
5791         headers = get_selected_headers (window);
5792         if (!headers)
5793                 return;
5794
5795         /* Pick the account */
5796         iter = tny_list_create_iterator (headers);
5797         header = TNY_HEADER (tny_iterator_get_current (iter));
5798         folder = tny_header_get_folder (header);
5799         account = tny_folder_get_account (folder);
5800         g_object_unref (folder);
5801         g_object_unref (header);
5802         g_object_unref (iter);
5803
5804         /* Connect and perform the message retrieval */
5805         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5806                                              g_object_ref (account),
5807                                              retrieve_msg_contents_performer,
5808                                              g_object_ref (headers));
5809
5810         /* Frees */
5811         g_object_unref (account);
5812         g_object_unref (headers);
5813 }
5814
5815 void
5816 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5817 {
5818         g_return_if_fail (MODEST_IS_WINDOW (window));
5819
5820         /* Update dimmed */
5821         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5822 }
5823
5824 void
5825 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5826 {
5827         g_return_if_fail (MODEST_IS_WINDOW (window));
5828
5829         /* Update dimmed */
5830         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5831 }
5832
5833 void
5834 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5835                                           ModestWindow *window)
5836 {
5837         g_return_if_fail (MODEST_IS_WINDOW (window));
5838
5839         /* Update dimmed */
5840         modest_ui_actions_check_menu_dimming_rules (window);
5841 }
5842
5843 void
5844 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5845                                           ModestWindow *window)
5846 {
5847         g_return_if_fail (MODEST_IS_WINDOW (window));
5848
5849         /* Update dimmed */
5850         modest_ui_actions_check_menu_dimming_rules (window);
5851 }
5852
5853 void
5854 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5855                                           ModestWindow *window)
5856 {
5857         g_return_if_fail (MODEST_IS_WINDOW (window));
5858
5859         /* Update dimmed */
5860         modest_ui_actions_check_menu_dimming_rules (window);
5861 }
5862
5863 void
5864 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5865                                             ModestWindow *window)
5866 {
5867         g_return_if_fail (MODEST_IS_WINDOW (window));
5868
5869         /* Update dimmed */
5870         modest_ui_actions_check_menu_dimming_rules (window);
5871 }
5872
5873 void
5874 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5875                                           ModestWindow *window)
5876 {
5877         g_return_if_fail (MODEST_IS_WINDOW (window));
5878
5879         /* Update dimmed */
5880         modest_ui_actions_check_menu_dimming_rules (window);
5881 }
5882
5883 void
5884 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5885                                           ModestWindow *window)
5886 {
5887         g_return_if_fail (MODEST_IS_WINDOW (window));
5888
5889         /* Update dimmed */
5890         modest_ui_actions_check_menu_dimming_rules (window);
5891 }
5892
5893 void
5894 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5895                                                  ModestWindow *window)
5896 {
5897         g_return_if_fail (MODEST_IS_WINDOW (window));
5898
5899         /* Update dimmed */
5900         modest_ui_actions_check_menu_dimming_rules (window);
5901 }
5902
5903 void
5904 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5905                                                      ModestWindow *window)
5906 {
5907         g_return_if_fail (MODEST_IS_WINDOW (window));
5908
5909         /* Update dimmed */
5910         modest_ui_actions_check_menu_dimming_rules (window);
5911 }
5912
5913 void
5914 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5915                                                      ModestWindow *window)
5916 {
5917         g_return_if_fail (MODEST_IS_WINDOW (window));
5918
5919         /* Update dimmed */
5920         modest_ui_actions_check_menu_dimming_rules (window);
5921 }
5922
5923 void
5924 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5925 {
5926         g_return_if_fail (MODEST_IS_WINDOW (window));
5927
5928         /* we check for low-mem; in that case, show a warning, and don't allow
5929          * searching
5930          */
5931         if (modest_platform_check_memory_low (window, TRUE))
5932                 return;
5933
5934         modest_platform_show_search_messages (GTK_WINDOW (window));
5935 }
5936
5937 void
5938 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5939 {
5940         g_return_if_fail (MODEST_IS_WINDOW (win));
5941
5942
5943         /* we check for low-mem; in that case, show a warning, and don't allow
5944          * for the addressbook
5945          */
5946         if (modest_platform_check_memory_low (win, TRUE))
5947                 return;
5948
5949
5950         modest_platform_show_addressbook (GTK_WINDOW (win));
5951 }
5952
5953
5954 void
5955 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
5956                                           ModestWindow *window)
5957 {
5958         gboolean active;
5959         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5960
5961         if (GTK_IS_TOGGLE_ACTION (action))
5962                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
5963         else
5964                 active = TRUE;
5965
5966         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
5967                                                        active);
5968 }
5969
5970 #ifndef MODEST_TOOLKIT_HILDON2
5971 static void
5972 on_send_receive_finished (ModestMailOperation  *mail_op,
5973                            gpointer user_data)
5974 {
5975         GtkWidget *header_view, *folder_view;
5976         TnyFolderStore *folder_store;
5977         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5978
5979         /* Set send/receive operation finished */
5980         modest_main_window_notify_send_receive_completed (main_win);
5981
5982         /* Don't refresh the current folder if there were any errors */
5983         if (modest_mail_operation_get_status (mail_op) !=
5984             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5985                 return;
5986
5987         /* Refresh the current folder if we're viewing a window. We do
5988            this because the user won't be able to see the new mails in
5989            the selected folder after a Send&Receive because it only
5990            performs a poke_status, i.e, only the number of read/unread
5991            messages is updated, but the new headers are not
5992            downloaded */
5993         folder_view = modest_main_window_get_child_widget (main_win,
5994                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5995         if (!folder_view)
5996                 return;
5997
5998         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5999
6000         /* Do not need to refresh INBOX again because the
6001            update_account does it always automatically */
6002         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6003             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6004                 ModestMailOperation *refresh_op;
6005
6006                 header_view = modest_main_window_get_child_widget (main_win,
6007                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6008
6009                 /* We do not need to set the contents style
6010                    because it hasn't changed. We also do not
6011                    need to save the widget status. Just force
6012                    a refresh */
6013                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6014                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6015                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6016                                                       folder_refreshed_cb, main_win);
6017                 g_object_unref (refresh_op);
6018         }
6019
6020         if (folder_store)
6021                 g_object_unref (folder_store);
6022 }
6023 #endif
6024
6025 void
6026 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6027                                                 TnyHeader *header,
6028                                                 TnyMsg *msg,
6029                                                 GError *err,
6030                                                 gpointer user_data)
6031 {
6032         const gchar* server_name = NULL;
6033         TnyTransportAccount *transport;
6034         gchar *message = NULL;
6035         ModestProtocol *protocol;
6036
6037         /* Don't show anything if the user cancelled something or the
6038          * send receive request is not interactive. Authentication
6039          * errors are managed by the account store so no need to show
6040          * a dialog here again */
6041         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6042             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6043             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6044                 return;
6045
6046
6047         /* Get the server name. Note that we could be using a
6048            connection specific transport account */
6049         transport = (TnyTransportAccount *)
6050                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6051         if (transport) {
6052                 ModestTnyAccountStore *acc_store;
6053                 const gchar *acc_name;
6054                 TnyTransportAccount *conn_specific;
6055
6056                 acc_store = modest_runtime_get_account_store();
6057                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6058                 conn_specific = (TnyTransportAccount *)
6059                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6060                 if (conn_specific) {
6061                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6062                         g_object_unref (conn_specific);
6063                 } else {
6064                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6065                 }
6066                 g_object_unref (transport);
6067         }
6068
6069         /* Get protocol */
6070         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6071                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6072                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6073         if (!protocol) {
6074                 g_warning ("%s: Account with no proto", __FUNCTION__);
6075                 return;
6076         }
6077
6078         /* Show the appropriate message text for the GError: */
6079         switch (err->code) {
6080         case TNY_SERVICE_ERROR_CONNECT:
6081                 message = modest_protocol_get_translation (protocol,
6082                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6083                                                            server_name);
6084                 break;
6085         case TNY_SERVICE_ERROR_SEND:
6086                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6087                 break;
6088         case TNY_SERVICE_ERROR_UNAVAILABLE:
6089                 message = modest_protocol_get_translation (protocol,
6090                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6091                                                            server_name);
6092                 break;
6093         default:
6094                 g_warning ("%s: unexpected ERROR %d",
6095                            __FUNCTION__, err->code);
6096                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6097                 break;
6098         }
6099
6100         modest_platform_run_information_dialog (NULL, message, FALSE);
6101         g_free (message);
6102 }
6103
6104 void
6105 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6106                                                 gchar *msg_id,
6107                                                 guint status,
6108                                                 gpointer user_data)
6109 {
6110         ModestWindow *top_window = NULL;
6111         ModestWindowMgr *mgr = NULL;
6112         GtkWidget *header_view = NULL;
6113         TnyFolder *selected_folder = NULL;
6114         TnyFolderType folder_type;
6115
6116         mgr = modest_runtime_get_window_mgr ();
6117         top_window = modest_window_mgr_get_current_top (mgr);
6118
6119         if (!top_window)
6120                 return;
6121
6122         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6123                 header_view = (GtkWidget *)
6124                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6125         }
6126
6127         /* Get selected folder */
6128         if (header_view)
6129                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6130         if (!selected_folder)
6131                 return;
6132
6133         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6134 #if GTK_CHECK_VERSION(2, 8, 0)
6135         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6136         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6137                 GtkTreeViewColumn *tree_column;
6138
6139                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6140                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6141                 if (tree_column)
6142                         gtk_tree_view_column_queue_resize (tree_column);
6143                 }
6144 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6145         gtk_widget_queue_draw (header_view);
6146 #endif
6147
6148 #ifndef MODEST_TOOLKIT_HILDON2
6149         /* Rerun dimming rules, because the message could become deletable for example */
6150         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6151                                                  MODEST_DIMMING_RULES_TOOLBAR);
6152         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6153                                                  MODEST_DIMMING_RULES_MENU);
6154 #endif
6155
6156         /* Free */
6157         g_object_unref (selected_folder);
6158 }
6159
6160 void
6161 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6162                                                TnyAccount *account)
6163 {
6164         ModestProtocolType protocol_type;
6165         ModestProtocol *protocol;
6166         gchar *error_note = NULL;
6167
6168         protocol_type = modest_tny_account_get_protocol_type (account);
6169         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6170                                                                   protocol_type);
6171
6172         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6173         if (error_note == NULL) {
6174                 g_warning ("%s: This should not be reached", __FUNCTION__);
6175         } else {
6176                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6177                 g_free (error_note);
6178         }
6179 }
6180
6181 gchar *
6182 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6183 {
6184         gchar *msg = NULL;
6185         gchar *subject;
6186         TnyFolderStore *folder = NULL;
6187         TnyAccount *account = NULL;
6188         ModestProtocolType proto;
6189         ModestProtocol *protocol;
6190         TnyHeader *header = NULL;
6191
6192         if (MODEST_IS_HEADER_WINDOW (win)) {
6193                 GtkWidget *header_view;
6194                 TnyList* headers = NULL;
6195                 TnyIterator *iter;
6196                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6197                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6198                 if (!headers || tny_list_get_length (headers) == 0) {
6199                         if (headers)
6200                                 g_object_unref (headers);
6201                         return NULL;
6202                 }
6203                 iter = tny_list_create_iterator (headers);
6204                 header = TNY_HEADER (tny_iterator_get_current (iter));
6205                 if (header) {
6206                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6207                 } else {
6208                         g_warning ("List should contain headers");
6209                 }
6210                 g_object_unref (iter);
6211                 g_object_unref (headers);
6212         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6213                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6214                 if (header)
6215                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6216         }
6217
6218         if (!header || !folder)
6219                 goto frees;
6220
6221         /* Get the account type */
6222         account = tny_folder_get_account (TNY_FOLDER (folder));
6223         proto = modest_tny_account_get_protocol_type (account);
6224         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6225                                                                   proto);
6226
6227         subject = tny_header_dup_subject (header);
6228         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6229         if (subject)
6230                 g_free (subject);
6231         if (msg == NULL) {
6232                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6233         }
6234
6235  frees:
6236         /* Frees */
6237         if (account)
6238                 g_object_unref (account);
6239         if (folder)
6240                 g_object_unref (folder);
6241         if (header)
6242                 g_object_unref (header);
6243
6244         return msg;
6245 }
6246
6247 gboolean
6248 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6249                                      const gchar *account_name,
6250                                      const gchar *account_title)
6251 {
6252         ModestAccountMgr *account_mgr;
6253         gchar *txt = NULL;
6254         gint response;
6255         ModestProtocol *protocol;
6256         gboolean removed = FALSE;
6257
6258         g_return_val_if_fail (account_name, FALSE);
6259         g_return_val_if_fail (account_title, FALSE);
6260
6261         account_mgr = modest_runtime_get_account_mgr();
6262
6263         /* The warning text depends on the account type: */
6264         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6265                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6266                                                                                                          account_name));
6267         txt = modest_protocol_get_translation (protocol,
6268                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6269                                                account_title);
6270         if (txt == NULL)
6271                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6272
6273         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6274         g_free (txt);
6275         txt = NULL;
6276
6277         if (response == GTK_RESPONSE_OK) {
6278                 /* Remove account. If it succeeds then it also removes
6279                    the account from the ModestAccountView: */
6280                 gboolean is_default = FALSE;
6281                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6282                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6283                         is_default = TRUE;
6284                 g_free (default_account_name);
6285
6286                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6287                 if (removed) {
6288                         /* Close all email notifications, we cannot
6289                            distinguish if the notification belongs to
6290                            this account or not, so for safety reasons
6291                            we remove them all */
6292                         modest_platform_remove_new_mail_notifications (FALSE);
6293                 } else {
6294                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6295                 }
6296         }
6297         return removed;
6298 }
6299
6300 static void
6301 on_fetch_images_performer (gboolean canceled,
6302                            GError *err,
6303                            GtkWindow *parent_window,
6304                            TnyAccount *account,
6305                            gpointer user_data)
6306 {
6307         if (err || canceled) {
6308                 /* Show an unable to retrieve images ??? */
6309                 return;
6310         }
6311
6312         /* Note that the user could have closed the window while connecting */
6313         if (GTK_WIDGET_VISIBLE (parent_window))
6314                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6315         g_object_unref ((GObject *) user_data);
6316 }
6317
6318 void
6319 modest_ui_actions_on_fetch_images (GtkAction *action,
6320                                    ModestWindow *window)
6321 {
6322         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6323
6324         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6325                                              NULL,
6326                                              on_fetch_images_performer, 
6327                                              g_object_ref (window));
6328 }
6329
6330 void
6331 modest_ui_actions_on_reload_message (const gchar *msg_id)
6332 {
6333         ModestWindow *window = NULL;
6334
6335         g_return_if_fail (msg_id && msg_id[0] != '\0');
6336         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6337                                                             msg_id,
6338                                                             &window))
6339                 return;
6340
6341
6342         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6343                 return;
6344
6345         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6346 }
6347
6348 /** Check whether any connections are active, and cancel them if 
6349  * the user wishes.
6350  * Returns TRUE is there was no problem, 
6351  * or if an operation was cancelled so we can continue.
6352  * Returns FALSE if the user chose to cancel his request instead.
6353  */
6354
6355 gboolean
6356 modest_ui_actions_check_for_active_account (ModestWindow *self,
6357                                             const gchar* account_name)
6358 {
6359         ModestTnySendQueue *send_queue;
6360         ModestTnyAccountStore *acc_store;
6361         ModestMailOperationQueue* queue;
6362         TnyConnectionStatus store_conn_status;
6363         TnyAccount *store_account = NULL, *transport_account = NULL;
6364         gboolean retval = TRUE, sending = FALSE;
6365
6366         acc_store = modest_runtime_get_account_store ();
6367         queue = modest_runtime_get_mail_operation_queue ();
6368
6369         store_account = 
6370                 modest_tny_account_store_get_server_account (acc_store,
6371                                                              account_name,
6372                                                              TNY_ACCOUNT_TYPE_STORE);
6373
6374         /* This could happen if the account was deleted before the
6375            call to this function */
6376         if (!store_account)
6377                 return FALSE;
6378
6379         transport_account = 
6380                 modest_tny_account_store_get_server_account (acc_store,
6381                                                              account_name,
6382                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
6383
6384         /* This could happen if the account was deleted before the
6385            call to this function */
6386         if (!transport_account) {
6387                 g_object_unref (store_account);
6388                 return FALSE;
6389         }
6390
6391         /* If the transport account was not used yet, then the send
6392            queue could not exist (it's created on demand) */
6393         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
6394         if (TNY_IS_SEND_QUEUE (send_queue))
6395                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
6396
6397         store_conn_status = tny_account_get_connection_status (store_account);
6398         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
6399                 gint response;
6400
6401                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
6402                                                                 _("emev_nc_disconnect_account"));
6403                 if (response == GTK_RESPONSE_OK) {
6404                         retval = TRUE;
6405                 } else {
6406                         retval = FALSE;
6407                 }
6408         }
6409
6410         if (retval) {
6411
6412                 /* FIXME: We should only cancel those of this account */
6413                 modest_mail_operation_queue_cancel_all (queue);
6414
6415                 /* Also disconnect the account */
6416                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
6417                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
6418                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
6419                                                       FALSE, NULL, NULL);
6420                 }
6421                 if (sending) {
6422                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
6423                                                       FALSE, NULL, NULL);
6424                 }
6425         }
6426                 
6427         /* Frees */
6428         g_object_unref (store_account);
6429         g_object_unref (transport_account);
6430         
6431         return retval;
6432 }