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