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