Compilation fixes
[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         GtkWindow *toplevel;
4405
4406         helper = (MoveToInfo *) user_data;
4407
4408         parent_win = (GtkWidget *) helper->win;
4409         toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) parent_win);
4410         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4411                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4412         switch (response) {
4413                 TnyFolderStore *dst_folder;
4414                 TnyFolderStore *selected;
4415
4416         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4417                 selected = modest_folder_view_get_selected (folder_view);
4418                 modest_ui_actions_create_folder ((GtkWindow *) dialog, GTK_WIDGET (folder_view), selected);
4419                 g_object_unref (selected);
4420                 return;
4421         case GTK_RESPONSE_NONE:
4422         case GTK_RESPONSE_CANCEL:
4423         case GTK_RESPONSE_DELETE_EVENT:
4424                 break;
4425         case GTK_RESPONSE_OK:
4426                 dst_folder = modest_folder_view_get_selected (folder_view);
4427
4428                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4429                         /* Clean list to move used for filtering */
4430                         modest_folder_view_set_list_to_move (folder_view, NULL);
4431
4432                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4433                                                                     dst_folder,
4434                                                                     helper->list,
4435                                                                     toplevel);
4436                 } else {
4437                         /* if the user selected a root folder
4438                            (account) then do not perform any action */
4439                         if (TNY_IS_ACCOUNT (dst_folder)) {
4440                                 g_signal_stop_emission_by_name (dialog, "response");
4441                                 return;
4442                         }
4443
4444                         /* Clean list to move used for filtering */
4445                         modest_folder_view_set_list_to_move (folder_view, NULL);
4446
4447                         /* Moving from headers window in edit mode */
4448                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4449                                                              dst_folder,
4450                                                              MODEST_WINDOW (parent_win));
4451                 }
4452
4453                 if (dst_folder)
4454                         g_object_unref (dst_folder);
4455
4456                 unset_edit_mode = TRUE;
4457                 break;
4458         default:
4459                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4460         }
4461
4462         /* Free the helper and exit */
4463         if (helper->list)
4464                 g_object_unref (helper->list);
4465         if (unset_edit_mode) {
4466 #ifdef MODEST_TOOLKIT_HILDON2
4467                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
4468 #endif
4469         }
4470         g_slice_free (MoveToInfo, helper);
4471         gtk_widget_destroy (GTK_WIDGET (dialog));
4472 }
4473
4474 static GtkWidget*
4475 create_move_to_dialog (GtkWindow *win,
4476                        GtkWidget *folder_view,
4477                        TnyList *list_to_move)
4478 {
4479         GtkWidget *dialog, *tree_view = NULL;
4480
4481         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
4482
4483
4484         /* It could happen that we're trying to move a message from a
4485            window (msg window for example) after the main window was
4486            closed, so we can not just get the model of the folder
4487            view */
4488         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4489                 const gchar *visible_id = NULL;
4490
4491                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4492                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4493                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4494                                                MODEST_FOLDER_VIEW(tree_view));
4495
4496                 visible_id =
4497                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4498
4499                 /* Show the same account than the one that is shown in the main window */
4500                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
4501                                                                              visible_id);
4502         } else {
4503                 const gchar *active_account_name = NULL;
4504                 ModestAccountMgr *mgr = NULL;
4505                 ModestAccountSettings *settings = NULL;
4506                 ModestServerAccountSettings *store_settings = NULL;
4507
4508                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4509                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4510                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
4511                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
4512
4513                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4514                 mgr = modest_runtime_get_account_mgr ();
4515                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4516
4517                 if (settings) {
4518                         const gchar *store_account_name;
4519                         store_settings = modest_account_settings_get_store_settings (settings);
4520                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4521
4522                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
4523                                                                                      store_account_name);
4524                         g_object_unref (store_settings);
4525                         g_object_unref (settings);
4526                 }
4527         }
4528
4529         /* we keep a pointer to the embedded folder view, so we can
4530          *   retrieve it with get_folder_view_from_move_to_dialog (see
4531          *   above) later (needed for focus handling)
4532          */
4533         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
4534
4535         /* Hide special folders */
4536         if (list_to_move)
4537                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
4538
4539         gtk_widget_show (GTK_WIDGET (tree_view));
4540
4541         return dialog;
4542 }
4543
4544 /*
4545  * Shows a confirmation dialog to the user when we're moving messages
4546  * from a remote server to the local storage. Returns the dialog
4547  * response. If it's other kind of movement then it always returns
4548  * GTK_RESPONSE_OK
4549  *
4550  * This one is used by the next functions:
4551  *      modest_ui_actions_on_paste                      - commented out
4552  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4553  */
4554 gint
4555 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4556                                              TnyFolder *dest_folder,
4557                                              gboolean delete,
4558                                              TnyList *headers)
4559 {
4560         gint response = GTK_RESPONSE_OK;
4561         TnyAccount *account = NULL;
4562         TnyFolder *src_folder = NULL;
4563         TnyIterator *iter = NULL;
4564         TnyHeader *header = NULL;
4565
4566         /* return with OK if the destination is a remote folder */
4567         if (modest_tny_folder_is_remote_folder (dest_folder))
4568                 return GTK_RESPONSE_OK;
4569
4570         /* Get source folder */
4571         iter = tny_list_create_iterator (headers);
4572         header = TNY_HEADER (tny_iterator_get_current (iter));
4573         if (header) {
4574                 src_folder = tny_header_get_folder (header);
4575                 g_object_unref (header);
4576         }
4577         g_object_unref (iter);
4578
4579         /* if no src_folder, message may be an attahcment */
4580         if (src_folder == NULL)
4581                 return GTK_RESPONSE_CANCEL;
4582
4583         /* If the source is a local or MMC folder */
4584         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4585                 g_object_unref (src_folder);
4586                 return GTK_RESPONSE_OK;
4587         }
4588
4589         /* Get the account */
4590         account = tny_folder_get_account (src_folder);
4591
4592         /* now if offline we ask the user */
4593         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4594                 response = GTK_RESPONSE_OK;
4595         else
4596                 response = GTK_RESPONSE_CANCEL;
4597
4598         /* Frees */
4599         g_object_unref (src_folder);
4600         g_object_unref (account);
4601
4602         return response;
4603 }
4604
4605 static void
4606 move_to_helper_destroyer (gpointer user_data)
4607 {
4608         MoveToHelper *helper = (MoveToHelper *) user_data;
4609
4610         /* Close the "Pasting" information banner */
4611         if (helper->banner) {
4612                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4613                 g_object_unref (helper->banner);
4614         }
4615         if (gtk_tree_row_reference_valid (helper->reference)) {
4616                 gtk_tree_row_reference_free (helper->reference);
4617                 helper->reference = NULL;
4618         }
4619         g_free (helper);
4620 }
4621
4622 static void
4623 move_to_cb (ModestMailOperation *mail_op,
4624             gpointer user_data)
4625 {
4626         MoveToHelper *helper = (MoveToHelper *) user_data;
4627         GObject *object = modest_mail_operation_get_source (mail_op);
4628
4629         /* Note that the operation could have failed, in that case do
4630            nothing */
4631         if (modest_mail_operation_get_status (mail_op) !=
4632             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4633                 goto frees;
4634
4635         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4636                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4637
4638                 if (!modest_msg_view_window_select_next_message (self) &&
4639                     !modest_msg_view_window_select_previous_message (self)) {
4640                         /* No more messages to view, so close this window */
4641                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4642                 }
4643         }
4644         g_object_unref (object);
4645
4646  frees:
4647         /* Destroy the helper */
4648         move_to_helper_destroyer (helper);
4649 }
4650
4651 static void
4652 folder_move_to_cb (ModestMailOperation *mail_op,
4653                    TnyFolder *new_folder,
4654                    gpointer user_data)
4655 {
4656         GObject *object;
4657
4658         object = modest_mail_operation_get_source (mail_op);
4659         {
4660                 move_to_cb (mail_op, user_data);
4661         }
4662 }
4663
4664 static void
4665 msgs_move_to_cb (ModestMailOperation *mail_op,
4666                  gpointer user_data)
4667 {
4668         move_to_cb (mail_op, user_data);
4669 }
4670
4671 void
4672 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4673                                              gpointer user_data)
4674 {
4675         GObject *win = NULL;
4676         const GError *error;
4677         TnyAccount *account = NULL;
4678
4679         win = modest_mail_operation_get_source (mail_op);
4680         error = modest_mail_operation_get_error (mail_op);
4681
4682         if (TNY_IS_FOLDER (user_data))
4683                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
4684         else if (TNY_IS_ACCOUNT (user_data))
4685                 account = g_object_ref (user_data);
4686
4687         /* If it's not a disk full error then show a generic error */
4688         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4689                                                              (GtkWidget *) win, (GError *) error,
4690                                                              account, NULL))
4691                 modest_platform_run_information_dialog ((GtkWindow *) win,
4692                                                         _("mail_in_ui_folder_move_target_error"),
4693                                                         FALSE);
4694         if (account)
4695                 g_object_unref (account);
4696         if (win)
4697                 g_object_unref (win);
4698 }
4699
4700
4701 /*
4702  * Checks if we need a connection to do the transfer and if the user
4703  * wants to connect to complete it
4704  */
4705 static void
4706 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4707                                        TnyFolderStore *src_folder,
4708                                        TnyList *headers,
4709                                        TnyFolder *dst_folder,
4710                                        gboolean delete_originals,
4711                                        gboolean *need_connection,
4712                                        gboolean *do_xfer)
4713 {
4714         TnyAccount *src_account;
4715         gint uncached_msgs = 0;
4716
4717         /* We don't need any further check if
4718          *
4719          * 1- the source folder is local OR
4720          * 2- the device is already online
4721          */
4722         if (!modest_tny_folder_store_is_remote (src_folder) ||
4723             tny_device_is_online (modest_runtime_get_device())) {
4724                 *need_connection = FALSE;
4725                 *do_xfer = TRUE;
4726                 return;
4727         }
4728
4729         /* We must ask for a connection when
4730          *
4731          *   - the message(s) is not already cached   OR
4732          *   - the message(s) is cached but the leave_on_server setting
4733          * is FALSE (because we need to sync the source folder to
4734          * delete the message from the server (for IMAP we could do it
4735          * offline, it'll take place the next time we get a
4736          * connection)
4737          */
4738         uncached_msgs = header_list_count_uncached_msgs (headers);
4739         src_account = get_account_from_folder_store (src_folder);
4740         if (uncached_msgs > 0) {
4741                 guint num_headers;
4742                 const gchar *msg;
4743
4744                 *need_connection = TRUE;
4745                 num_headers = tny_list_get_length (headers);
4746                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4747
4748                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4749                     GTK_RESPONSE_CANCEL) {
4750                         *do_xfer = FALSE;
4751                 } else {
4752                         *do_xfer = TRUE;
4753                 }
4754         } else {
4755                 /* The transfer is possible and the user wants to */
4756                 *do_xfer = TRUE;
4757
4758                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
4759                         const gchar *account_name;
4760                         gboolean leave_on_server;
4761
4762                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4763                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4764                                                                                   account_name);
4765
4766                         if (leave_on_server == TRUE) {
4767                                 *need_connection = FALSE;
4768                         } else {
4769                                 *need_connection = TRUE;
4770                         }
4771                 } else {
4772                         *need_connection = FALSE;
4773                 }
4774         }
4775
4776         /* Frees */
4777         g_object_unref (src_account);
4778 }
4779
4780 static void
4781 xfer_messages_error_handler (ModestMailOperation *mail_op,
4782                              gpointer user_data)
4783 {
4784         GObject *win;
4785         const GError *error;
4786         TnyAccount *account;
4787
4788         win = modest_mail_operation_get_source (mail_op);
4789         error = modest_mail_operation_get_error (mail_op);
4790
4791         /* We cannot get the account from the mail op as that is the
4792            source account and for checking memory full conditions we
4793            need the destination one */
4794         account = TNY_ACCOUNT (user_data);
4795
4796         if (error &&
4797             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4798                                                              (GtkWidget *) win, (GError*) error,
4799                                                              account, _KR("cerm_memory_card_full"))) {
4800                 modest_platform_run_information_dialog ((GtkWindow *) win,
4801                                                         _("mail_in_ui_folder_move_target_error"),
4802                                                         FALSE);
4803         }
4804         if (win)
4805                 g_object_unref (win);
4806 }
4807
4808 typedef struct {
4809         TnyFolderStore *dst_folder;
4810         TnyList *headers;
4811 } XferMsgsHelper;
4812
4813 /**
4814  * Utility function that transfer messages from both the main window
4815  * and the msg view window when using the "Move to" dialog
4816  */
4817 static void
4818 xfer_messages_performer  (gboolean canceled,
4819                           GError *err,
4820                           GtkWindow *parent_window,
4821                           TnyAccount *account,
4822                           gpointer user_data)
4823 {
4824         ModestWindow *win = MODEST_WINDOW (parent_window);
4825         TnyAccount *dst_account = NULL;
4826         gboolean dst_forbids_message_add = FALSE;
4827         XferMsgsHelper *helper;
4828         MoveToHelper *movehelper;
4829         ModestMailOperation *mail_op;
4830
4831         helper = (XferMsgsHelper *) user_data;
4832
4833         if (canceled || err) {
4834                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4835                                                                      (GtkWidget *) parent_window, err,
4836                                                                      account, NULL)) {
4837                         /* Show the proper error message */
4838                         modest_ui_actions_on_account_connection_error (parent_window, account);
4839                 }
4840                 goto end;
4841         }
4842
4843         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
4844
4845         /* tinymail will return NULL for local folders it seems */
4846         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4847                                                                                   modest_tny_account_get_protocol_type (dst_account),
4848                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
4849
4850         if (dst_forbids_message_add) {
4851                 modest_platform_information_banner (GTK_WIDGET (win),
4852                                                     NULL,
4853                                                     ngettext("mail_in_ui_folder_move_target_error",
4854                                                              "mail_in_ui_folder_move_targets_error",
4855                                                              tny_list_get_length (helper->headers)));
4856                 goto end;
4857         }
4858
4859         movehelper = g_new0 (MoveToHelper, 1);
4860
4861
4862         /* Perform the mail operation */
4863         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4864                                                                  xfer_messages_error_handler,
4865                                                                  g_object_ref (dst_account),
4866                                                                  g_object_unref);
4867         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4868                                          mail_op);
4869
4870         modest_mail_operation_xfer_msgs (mail_op,
4871                                          helper->headers,
4872                                          TNY_FOLDER (helper->dst_folder),
4873                                          TRUE,
4874                                          msgs_move_to_cb,
4875                                          movehelper);
4876
4877         g_object_unref (G_OBJECT (mail_op));
4878  end:
4879         if (dst_account)
4880                 g_object_unref (dst_account);
4881         g_object_unref (helper->dst_folder);
4882         g_object_unref (helper->headers);
4883         g_slice_free (XferMsgsHelper, helper);
4884 }
4885
4886 typedef struct {
4887         TnyFolder *src_folder;
4888         TnyFolderStore *dst_folder;
4889         gboolean delete_original;
4890         GtkWidget *folder_view;
4891 } MoveFolderInfo;
4892
4893 static void
4894 on_move_folder_cb (gboolean canceled,
4895                    GError *err,
4896                    GtkWindow *parent_window,
4897                    TnyAccount *account,
4898                    gpointer user_data)
4899 {
4900         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4901         GtkTreeSelection *sel;
4902         ModestMailOperation *mail_op = NULL;
4903
4904         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
4905                 /* Note that the connection process can fail due to
4906                    memory low conditions as it can not successfully
4907                    store the summary */
4908                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4909                                                                      (GtkWidget*) parent_window, err,
4910                                                                      account, NULL))
4911                         g_debug ("Error connecting when trying to move a folder");
4912
4913                 g_object_unref (G_OBJECT (info->src_folder));
4914                 g_object_unref (G_OBJECT (info->dst_folder));
4915                 g_free (info);
4916                 return;
4917         }
4918
4919         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4920 #ifndef MODEST_TOOLKIT_HILDON2
4921         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4922                         _CS_PASTING);
4923         if (helper->banner != NULL)  {
4924                 g_object_ref (helper->banner);
4925                 gtk_widget_show (GTK_WIDGET(helper->banner));
4926         }
4927 #endif
4928         /* Clean folder on header view before moving it */
4929         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4930         gtk_tree_selection_unselect_all (sel);
4931
4932         /* Let gtk events run. We need that the folder
4933            view frees its reference to the source
4934            folder *before* issuing the mail operation
4935            so we need the signal handler of selection
4936            changed to happen before the mail
4937            operation
4938         while (gtk_events_pending ())
4939                 gtk_main_iteration ();   */
4940
4941         mail_op =
4942                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4943                                                                modest_ui_actions_move_folder_error_handler,
4944                                                                g_object_ref (info->dst_folder), g_object_unref);
4945         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4946                                          mail_op);
4947
4948         modest_mail_operation_xfer_folder (mail_op,
4949                         TNY_FOLDER (info->src_folder),
4950                         info->dst_folder,
4951                         info->delete_original,
4952                         folder_move_to_cb,
4953                         helper);
4954         g_object_unref (G_OBJECT (info->src_folder));
4955
4956         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
4957         /* } */
4958
4959         /* Unref mail operation */
4960         g_object_unref (G_OBJECT (mail_op));
4961         g_object_unref (G_OBJECT (info->dst_folder));
4962         g_free (user_data);
4963 }
4964
4965 static TnyAccount *
4966 get_account_from_folder_store (TnyFolderStore *folder_store)
4967 {
4968         if (TNY_IS_ACCOUNT (folder_store))
4969                 return g_object_ref (folder_store);
4970         else
4971                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4972 }
4973
4974 /*
4975  * UI handler for the "Move to" action when invoked from the
4976  * ModestFolderWindow
4977  */
4978 static void
4979 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
4980                                             TnyFolderStore *dst_folder,
4981                                             TnyList *selection,
4982                                             GtkWindow *win)
4983 {
4984         TnyFolderStore *src_folder = NULL;
4985         TnyIterator *iterator;
4986
4987         if (tny_list_get_length (selection) != 1)
4988                 return;
4989
4990         iterator = tny_list_create_iterator (selection);
4991         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
4992         g_object_unref (iterator);
4993
4994
4995         gboolean do_xfer = TRUE;
4996
4997         /* Allow only to transfer folders to the local root folder */
4998         if (TNY_IS_ACCOUNT (dst_folder) &&
4999             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5000             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5001                 do_xfer = FALSE;
5002                 /* Show an error */
5003                 modest_platform_run_information_dialog (win,
5004                                                         _("mail_in_ui_folder_move_target_error"),
5005                                                         FALSE);
5006         } else if (!TNY_IS_FOLDER (src_folder)) {
5007                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5008                 do_xfer = FALSE;
5009         }
5010
5011         if (do_xfer) {
5012                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5013                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5014
5015                 info->src_folder = g_object_ref (src_folder);
5016                 info->dst_folder = g_object_ref (dst_folder);
5017                 info->delete_original = TRUE;
5018                 info->folder_view = folder_view;
5019
5020                 connect_info->callback = on_move_folder_cb;
5021                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5022                 connect_info->data = info;
5023
5024                 modest_platform_double_connect_and_perform(win, TRUE,
5025                                                            TNY_FOLDER_STORE (src_folder),
5026                                                            connect_info);
5027         }
5028
5029         /* Frees */
5030         g_object_unref (src_folder);
5031 }
5032
5033
5034 void
5035 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5036                                             TnyFolder *src_folder,
5037                                             TnyList *headers,
5038                                             TnyFolder *dst_folder)
5039 {
5040         gboolean need_connection = TRUE;
5041         gboolean do_xfer = TRUE;
5042         XferMsgsHelper *helper;
5043
5044         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5045         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5046         g_return_if_fail (TNY_IS_LIST (headers));
5047
5048         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5049                                                headers, TNY_FOLDER (dst_folder),
5050                                                TRUE, &need_connection,
5051                                                &do_xfer);
5052
5053         /* If we don't want to transfer just return */
5054         if (!do_xfer)
5055                 return;
5056
5057         /* Create the helper */
5058         helper = g_slice_new (XferMsgsHelper);
5059         helper->dst_folder = g_object_ref (dst_folder);
5060         helper->headers = g_object_ref (headers);
5061
5062         if (need_connection) {
5063                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5064                 connect_info->callback = xfer_messages_performer;
5065                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5066                 connect_info->data = helper;
5067
5068                 modest_platform_double_connect_and_perform(win, TRUE,
5069                                                            TNY_FOLDER_STORE (src_folder),
5070                                                            connect_info);
5071         } else {
5072                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5073                 xfer_messages_performer (FALSE, NULL, win,
5074                                          src_account, helper);
5075                 g_object_unref (src_account);
5076         }
5077 }
5078
5079 /*
5080  * UI handler for the "Move to" action when invoked from the
5081  * ModestMsgViewWindow
5082  */
5083 static void
5084 modest_ui_actions_on_window_move_to (GtkAction *action,
5085                                      TnyList *headers,
5086                                      TnyFolderStore *dst_folder,
5087                                      ModestWindow *win)
5088 {
5089         TnyFolder *src_folder = NULL;
5090
5091         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5092
5093         if (headers) {
5094                 TnyHeader *header = NULL;
5095                 TnyIterator *iter;
5096                 GtkWindow *toplevel;
5097
5098                 iter = tny_list_create_iterator (headers);
5099                 header = (TnyHeader *) tny_iterator_get_current (iter);
5100                 src_folder = tny_header_get_folder (header);
5101
5102                 /* Transfer the messages */
5103                 toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) win);
5104                 modest_ui_actions_transfer_messages_helper (toplevel, src_folder,
5105                                                             headers,
5106                                                             TNY_FOLDER (dst_folder));
5107
5108                 /* Frees */
5109                 g_object_unref (header);
5110                 g_object_unref (iter);
5111                 g_object_unref (src_folder);
5112         }
5113 }
5114
5115 void
5116 modest_ui_actions_on_move_to (GtkAction *action,
5117                               ModestWindow *win)
5118 {
5119         modest_ui_actions_on_edit_mode_move_to (win);
5120 }
5121
5122 gboolean
5123 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5124 {
5125         GtkWidget *dialog = NULL;
5126         GtkWindow *toplevel = NULL;
5127         MoveToInfo *helper = NULL;
5128         TnyList *list_to_move;
5129
5130         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5131
5132
5133         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5134
5135         if (!list_to_move)
5136                 return FALSE;
5137
5138         if (tny_list_get_length (list_to_move) < 1) {
5139                 g_object_unref (list_to_move);
5140                 return FALSE;
5141         }
5142
5143         /* Create and run the dialog */
5144         toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) win);
5145         dialog = create_move_to_dialog (toplevel, NULL, list_to_move);
5146         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5147                                      GTK_WINDOW (dialog),
5148                                      toplevel);
5149
5150         /* Create helper */
5151         helper = g_slice_new0 (MoveToInfo);
5152         helper->list = list_to_move;
5153         helper->win = win;
5154
5155         /* Listen to response signal */
5156         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5157
5158         /* Show the dialog */
5159         gtk_widget_show (dialog);
5160
5161         return FALSE;
5162 }
5163
5164 /*
5165  * Calls #HeadersFunc for each header already selected in the main
5166  * window or the message currently being shown in the msg view window
5167  */
5168 static void
5169 do_headers_action (ModestWindow *win,
5170                    HeadersFunc func,
5171                    gpointer user_data)
5172 {
5173         TnyList *headers_list = NULL;
5174         TnyIterator *iter = NULL;
5175         TnyHeader *header = NULL;
5176         TnyFolder *folder = NULL;
5177
5178         /* Get headers */
5179         headers_list = get_selected_headers (win);
5180         if (!headers_list)
5181                 return;
5182
5183         /* Get the folder */
5184         iter = tny_list_create_iterator (headers_list);
5185         header = TNY_HEADER (tny_iterator_get_current (iter));
5186         if (header) {
5187                 folder = tny_header_get_folder (header);
5188                 g_object_unref (header);
5189         }
5190
5191         /* Call the function for each header */
5192         while (!tny_iterator_is_done (iter)) {
5193                 header = TNY_HEADER (tny_iterator_get_current (iter));
5194                 func (header, win, user_data);
5195                 g_object_unref (header);
5196                 tny_iterator_next (iter);
5197         }
5198
5199         /* Trick: do a poke status in order to speed up the signaling
5200            of observers */
5201         if (folder) {
5202                 tny_folder_poke_status (folder);
5203                 g_object_unref (folder);
5204         }
5205
5206         /* Frees */
5207         g_object_unref (iter);
5208         g_object_unref (headers_list);
5209 }
5210
5211 void
5212 modest_ui_actions_view_attachment (GtkAction *action,
5213                                    ModestWindow *window)
5214 {
5215         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5216                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5217         } else {
5218                 /* not supported window for this action */
5219                 g_return_if_reached ();
5220         }
5221 }
5222
5223 void
5224 modest_ui_actions_save_attachments (GtkAction *action,
5225                                     ModestWindow *window)
5226 {
5227         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5228
5229                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5230                         return;
5231
5232                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5233         } else {
5234                 /* not supported window for this action */
5235                 g_return_if_reached ();
5236         }
5237 }
5238
5239 void
5240 modest_ui_actions_remove_attachments (GtkAction *action,
5241                                       ModestWindow *window)
5242 {
5243         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5244                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5245         } else {
5246                 /* not supported window for this action */
5247                 g_return_if_reached ();
5248         }
5249 }
5250
5251 void
5252 modest_ui_actions_on_settings (GtkAction *action,
5253                                ModestWindow *win)
5254 {
5255         GtkWidget *dialog;
5256         GtkWindow *toplevel;
5257
5258         dialog = modest_platform_get_global_settings_dialog ();
5259         toplevel = (GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (win));
5260         gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel);
5261         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5262         gtk_widget_show_all (dialog);
5263
5264         gtk_dialog_run (GTK_DIALOG (dialog));
5265
5266         gtk_widget_destroy (dialog);
5267 }
5268
5269 void
5270 modest_ui_actions_on_help (GtkAction *action,
5271                            GtkWindow *win)
5272 {
5273         /* Help app is not available at all in fremantle */
5274 #ifndef MODEST_TOOLKIT_HILDON2
5275         const gchar *help_id;
5276
5277         g_return_if_fail (win && GTK_IS_WINDOW(win));
5278
5279         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5280
5281         if (help_id)
5282                 modest_platform_show_help (win, help_id);
5283 #endif
5284 }
5285
5286 void
5287 modest_ui_actions_on_csm_help (GtkAction *action,
5288                                GtkWindow *win)
5289 {
5290         /* Help app is not available at all in fremantle */
5291 }
5292
5293 static void
5294 retrieve_contents_cb (ModestMailOperation *mail_op,
5295                       TnyHeader *header,
5296                       gboolean canceled,
5297                       TnyMsg *msg,
5298                       GError *err,
5299                       gpointer user_data)
5300 {
5301         /* We only need this callback to show an error in case of
5302            memory low condition */
5303         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5304                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
5305         }
5306 }
5307
5308 static void
5309 retrieve_msg_contents_performer (gboolean canceled,
5310                                  GError *err,
5311                                  GtkWindow *parent_window,
5312                                  TnyAccount *account,
5313                                  gpointer user_data)
5314 {
5315         ModestMailOperation *mail_op;
5316         TnyList *headers = TNY_LIST (user_data);
5317
5318         if (err || canceled) {
5319                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5320                                                                 (GtkWidget *) parent_window, err,
5321                                                                 account, NULL);
5322                 goto out;
5323         }
5324
5325         /* Create mail operation */
5326         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5327                                                                  modest_ui_actions_disk_operations_error_handler,
5328                                                                  NULL, NULL);
5329         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5330         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5331
5332         /* Frees */
5333         g_object_unref (mail_op);
5334  out:
5335         g_object_unref (headers);
5336         g_object_unref (account);
5337 }
5338
5339 void
5340 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5341                                             ModestWindow *window)
5342 {
5343         TnyList *headers = NULL;
5344         TnyAccount *account = NULL;
5345         TnyIterator *iter = NULL;
5346         TnyHeader *header = NULL;
5347         TnyFolder *folder = NULL;
5348
5349         /* Get headers */
5350         headers = get_selected_headers (window);
5351         if (!headers)
5352                 return;
5353
5354         /* Pick the account */
5355         iter = tny_list_create_iterator (headers);
5356         header = TNY_HEADER (tny_iterator_get_current (iter));
5357         folder = tny_header_get_folder (header);
5358         account = tny_folder_get_account (folder);
5359         g_object_unref (folder);
5360         g_object_unref (header);
5361         g_object_unref (iter);
5362
5363         /* Connect and perform the message retrieval */
5364         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5365                                              g_object_ref (account),
5366                                              retrieve_msg_contents_performer,
5367                                              g_object_ref (headers));
5368
5369         /* Frees */
5370         g_object_unref (account);
5371         g_object_unref (headers);
5372 }
5373
5374 void
5375 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5376 {
5377         g_return_if_fail (MODEST_IS_WINDOW (window));
5378
5379         /* Update dimmed */
5380         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5381 }
5382
5383 void
5384 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5385 {
5386         g_return_if_fail (MODEST_IS_WINDOW (window));
5387
5388         /* Update dimmed */
5389         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5390 }
5391
5392 void
5393 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5394                                           ModestWindow *window)
5395 {
5396         g_return_if_fail (MODEST_IS_WINDOW (window));
5397
5398         /* Update dimmed */
5399         modest_ui_actions_check_menu_dimming_rules (window);
5400 }
5401
5402 void
5403 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5404                                           ModestWindow *window)
5405 {
5406         g_return_if_fail (MODEST_IS_WINDOW (window));
5407
5408         /* Update dimmed */
5409         modest_ui_actions_check_menu_dimming_rules (window);
5410 }
5411
5412 void
5413 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5414                                           ModestWindow *window)
5415 {
5416         g_return_if_fail (MODEST_IS_WINDOW (window));
5417
5418         /* Update dimmed */
5419         modest_ui_actions_check_menu_dimming_rules (window);
5420 }
5421
5422 void
5423 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5424                                             ModestWindow *window)
5425 {
5426         g_return_if_fail (MODEST_IS_WINDOW (window));
5427
5428         /* Update dimmed */
5429         modest_ui_actions_check_menu_dimming_rules (window);
5430 }
5431
5432 void
5433 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5434                                           ModestWindow *window)
5435 {
5436         g_return_if_fail (MODEST_IS_WINDOW (window));
5437
5438         /* Update dimmed */
5439         modest_ui_actions_check_menu_dimming_rules (window);
5440 }
5441
5442 void
5443 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5444                                           ModestWindow *window)
5445 {
5446         g_return_if_fail (MODEST_IS_WINDOW (window));
5447
5448         /* Update dimmed */
5449         modest_ui_actions_check_menu_dimming_rules (window);
5450 }
5451
5452 void
5453 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5454                                                  ModestWindow *window)
5455 {
5456         g_return_if_fail (MODEST_IS_WINDOW (window));
5457
5458         /* Update dimmed */
5459         modest_ui_actions_check_menu_dimming_rules (window);
5460 }
5461
5462 void
5463 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5464                                                      ModestWindow *window)
5465 {
5466         g_return_if_fail (MODEST_IS_WINDOW (window));
5467
5468         /* Update dimmed */
5469         modest_ui_actions_check_menu_dimming_rules (window);
5470 }
5471
5472 void
5473 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5474                                                      ModestWindow *window)
5475 {
5476         g_return_if_fail (MODEST_IS_WINDOW (window));
5477
5478         /* Update dimmed */
5479         modest_ui_actions_check_menu_dimming_rules (window);
5480 }
5481
5482 void
5483 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5484 {
5485         GtkWindow *toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) window);
5486
5487         g_return_if_fail (MODEST_IS_WINDOW (window));
5488
5489         /* we check for low-mem; in that case, show a warning, and don't allow
5490          * searching
5491          */
5492         if (modest_platform_check_memory_low (window, TRUE))
5493                 return;
5494
5495         modest_platform_show_search_messages (toplevel);
5496 }
5497
5498 void
5499 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5500 {
5501         GtkWindow *toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) win);
5502
5503         g_return_if_fail (MODEST_IS_WINDOW (win));
5504
5505         /* we check for low-mem; in that case, show a warning, and don't allow
5506          * for the addressbook
5507          */
5508         if (modest_platform_check_memory_low (win, TRUE))
5509                 return;
5510
5511         modest_platform_show_addressbook (toplevel);
5512 }
5513
5514
5515 void
5516 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
5517                                           ModestWindow *window)
5518 {
5519         gboolean active;
5520         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5521
5522         if (GTK_IS_TOGGLE_ACTION (action))
5523                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
5524         else
5525                 active = TRUE;
5526
5527         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
5528                                                        active);
5529 }
5530
5531
5532 void
5533 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5534                                                 TnyHeader *header,
5535                                                 TnyMsg *msg,
5536                                                 GError *err,
5537                                                 gpointer user_data)
5538 {
5539         const gchar* server_name = NULL;
5540         TnyTransportAccount *transport;
5541         gchar *message = NULL;
5542         ModestProtocol *protocol;
5543
5544         /* Don't show anything if the user cancelled something or the
5545          * send receive request is not interactive. Authentication
5546          * errors are managed by the account store so no need to show
5547          * a dialog here again */
5548         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5549             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
5550             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5551                 return;
5552
5553
5554         /* Get the server name. Note that we could be using a
5555            connection specific transport account */
5556         transport = (TnyTransportAccount *)
5557                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
5558         if (transport) {
5559                 ModestTnyAccountStore *acc_store;
5560                 const gchar *acc_name;
5561                 TnyTransportAccount *conn_specific;
5562
5563                 acc_store = modest_runtime_get_account_store();
5564                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
5565                 conn_specific = (TnyTransportAccount *)
5566                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
5567                 if (conn_specific) {
5568                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
5569                         g_object_unref (conn_specific);
5570                 } else {
5571                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
5572                 }
5573                 g_object_unref (transport);
5574         }
5575
5576         /* Get protocol */
5577         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
5578                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
5579                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
5580         if (!protocol) {
5581                 g_warning ("%s: Account with no proto", __FUNCTION__);
5582                 return;
5583         }
5584
5585         /* Show the appropriate message text for the GError: */
5586         switch (err->code) {
5587         case TNY_SERVICE_ERROR_CONNECT:
5588                 message = modest_protocol_get_translation (protocol,
5589                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
5590                                                            server_name);
5591                 break;
5592         case TNY_SERVICE_ERROR_SEND:
5593                 message = g_strdup (_CS_UNABLE_TO_SEND);
5594                 break;
5595         case TNY_SERVICE_ERROR_UNAVAILABLE:
5596                 message = modest_protocol_get_translation (protocol,
5597                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
5598                                                            server_name);
5599                 break;
5600         default:
5601                 g_warning ("%s: unexpected ERROR %d",
5602                            __FUNCTION__, err->code);
5603                 message = g_strdup (_CS_UNABLE_TO_SEND);
5604                 break;
5605         }
5606
5607         modest_platform_run_information_dialog (NULL, message, FALSE);
5608         g_free (message);
5609 }
5610
5611 void
5612 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5613                                                 gchar *msg_id,
5614                                                 guint status,
5615                                                 gpointer user_data)
5616 {
5617         ModestWindow *top_window = NULL;
5618         ModestWindowMgr *mgr = NULL;
5619         GtkWidget *header_view = NULL;
5620         TnyFolder *selected_folder = NULL;
5621         TnyFolderType folder_type;
5622
5623         mgr = modest_runtime_get_window_mgr ();
5624         top_window = modest_window_mgr_get_current_top (mgr);
5625
5626         if (!top_window)
5627                 return;
5628
5629         if (MODEST_IS_HEADER_WINDOW (top_window)) {
5630                 header_view = (GtkWidget *)
5631                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
5632         }
5633
5634         /* Get selected folder */
5635         if (header_view)
5636                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
5637         if (!selected_folder)
5638                 return;
5639
5640         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5641 #if GTK_CHECK_VERSION(2, 8, 0)
5642         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
5643         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
5644                 GtkTreeViewColumn *tree_column;
5645
5646                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5647                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5648                 if (tree_column)
5649                         gtk_tree_view_column_queue_resize (tree_column);
5650                 }
5651 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
5652         gtk_widget_queue_draw (header_view);
5653 #endif
5654
5655 #ifndef MODEST_TOOLKIT_HILDON2
5656         /* Rerun dimming rules, because the message could become deletable for example */
5657         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5658                                                  MODEST_DIMMING_RULES_TOOLBAR);
5659         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5660                                                  MODEST_DIMMING_RULES_MENU);
5661 #endif
5662
5663         /* Free */
5664         g_object_unref (selected_folder);
5665 }
5666
5667 void
5668 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5669                                                TnyAccount *account)
5670 {
5671         ModestProtocolType protocol_type;
5672         ModestProtocol *protocol;
5673         gchar *error_note = NULL;
5674
5675         protocol_type = modest_tny_account_get_protocol_type (account);
5676         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5677                                                                   protocol_type);
5678
5679         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
5680         if (error_note == NULL) {
5681                 g_warning ("%s: This should not be reached", __FUNCTION__);
5682         } else {
5683                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5684                 g_free (error_note);
5685         }
5686 }
5687
5688 gchar *
5689 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5690 {
5691         gchar *msg = NULL;
5692         gchar *subject;
5693         TnyFolderStore *folder = NULL;
5694         TnyAccount *account = NULL;
5695         ModestProtocolType proto;
5696         ModestProtocol *protocol;
5697         TnyHeader *header = NULL;
5698
5699         if (MODEST_IS_HEADER_WINDOW (win)) {
5700                 GtkWidget *header_view;
5701                 TnyList* headers = NULL;
5702                 TnyIterator *iter;
5703                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
5704                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5705                 if (!headers || tny_list_get_length (headers) == 0) {
5706                         if (headers)
5707                                 g_object_unref (headers);
5708                         return NULL;
5709                 }
5710                 iter = tny_list_create_iterator (headers);
5711                 header = TNY_HEADER (tny_iterator_get_current (iter));
5712                 if (header) {
5713                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5714                 } else {
5715                         g_warning ("List should contain headers");
5716                 }
5717                 g_object_unref (iter);
5718                 g_object_unref (headers);
5719         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5720                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5721                 if (header)
5722                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5723         }
5724
5725         if (!header || !folder)
5726                 goto frees;
5727
5728         /* Get the account type */
5729         account = tny_folder_get_account (TNY_FOLDER (folder));
5730         proto = modest_tny_account_get_protocol_type (account);
5731         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5732                                                                   proto);
5733
5734         subject = tny_header_dup_subject (header);
5735         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
5736         if (subject)
5737                 g_free (subject);
5738         if (msg == NULL) {
5739                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5740         }
5741
5742  frees:
5743         /* Frees */
5744         if (account)
5745                 g_object_unref (account);
5746         if (folder)
5747                 g_object_unref (folder);
5748         if (header)
5749                 g_object_unref (header);
5750
5751         return msg;
5752 }
5753
5754 gboolean
5755 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
5756                                      const gchar *account_name,
5757                                      const gchar *account_title)
5758 {
5759         ModestAccountMgr *account_mgr;
5760         gchar *txt = NULL;
5761         gint response;
5762         ModestProtocol *protocol;
5763         gboolean removed = FALSE;
5764
5765         g_return_val_if_fail (account_name, FALSE);
5766         g_return_val_if_fail (account_title, FALSE);
5767
5768         account_mgr = modest_runtime_get_account_mgr();
5769
5770         /* The warning text depends on the account type: */
5771         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5772                                                                   modest_account_mgr_get_store_protocol (account_mgr,
5773                                                                                                          account_name));
5774         txt = modest_protocol_get_translation (protocol,
5775                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
5776                                                account_title);
5777         if (txt == NULL)
5778                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
5779
5780         response = modest_platform_run_confirmation_dialog (parent_window, txt);
5781         g_free (txt);
5782         txt = NULL;
5783
5784         if (response == GTK_RESPONSE_OK) {
5785                 /* Remove account. If it succeeds then it also removes
5786                    the account from the ModestAccountView: */
5787                 gboolean is_default = FALSE;
5788                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
5789                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
5790                         is_default = TRUE;
5791                 g_free (default_account_name);
5792
5793                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
5794                 if (removed) {
5795                         /* Close all email notifications, we cannot
5796                            distinguish if the notification belongs to
5797                            this account or not, so for safety reasons
5798                            we remove them all */
5799                         modest_platform_remove_new_mail_notifications (FALSE);
5800                 } else {
5801                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
5802                 }
5803         }
5804         return removed;
5805 }
5806
5807 static void
5808 on_fetch_images_performer (gboolean canceled,
5809                            GError *err,
5810                            GtkWindow *parent_window,
5811                            TnyAccount *account,
5812                            gpointer user_data)
5813 {
5814         if (err || canceled) {
5815                 /* Show an unable to retrieve images ??? */
5816                 return;
5817         }
5818
5819         /* Note that the user could have closed the window while connecting */
5820         if (GTK_WIDGET_VISIBLE (parent_window))
5821                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
5822         g_object_unref ((GObject *) user_data);
5823 }
5824
5825 void
5826 modest_ui_actions_on_fetch_images (GtkAction *action,
5827                                    ModestWindow *window)
5828 {
5829         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
5830
5831         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
5832                                              NULL,
5833                                              on_fetch_images_performer, 
5834                                              g_object_ref (window));
5835 }
5836
5837 void
5838 modest_ui_actions_on_reload_message (const gchar *msg_id)
5839 {
5840         ModestWindow *window = NULL;
5841
5842         g_return_if_fail (msg_id && msg_id[0] != '\0');
5843         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
5844                                                             msg_id,
5845                                                             &window))
5846                 return;
5847
5848
5849         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
5850                 return;
5851
5852         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
5853 }
5854
5855 /** Check whether any connections are active, and cancel them if 
5856  * the user wishes.
5857  * Returns TRUE is there was no problem, 
5858  * or if an operation was cancelled so we can continue.
5859  * Returns FALSE if the user chose to cancel his request instead.
5860  */
5861
5862 gboolean
5863 modest_ui_actions_check_for_active_account (ModestWindow *self,
5864                                             const gchar* account_name)
5865 {
5866         ModestTnySendQueue *send_queue;
5867         ModestTnyAccountStore *acc_store;
5868         ModestMailOperationQueue* queue;
5869         TnyConnectionStatus store_conn_status;
5870         TnyAccount *store_account = NULL, *transport_account = NULL;
5871         gboolean retval = TRUE, sending = FALSE;
5872
5873         acc_store = modest_runtime_get_account_store ();
5874         queue = modest_runtime_get_mail_operation_queue ();
5875
5876         store_account = 
5877                 modest_tny_account_store_get_server_account (acc_store,
5878                                                              account_name,
5879                                                              TNY_ACCOUNT_TYPE_STORE);
5880
5881         /* This could happen if the account was deleted before the
5882            call to this function */
5883         if (!store_account)
5884                 return FALSE;
5885
5886         transport_account = 
5887                 modest_tny_account_store_get_server_account (acc_store,
5888                                                              account_name,
5889                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
5890
5891         /* This could happen if the account was deleted before the
5892            call to this function */
5893         if (!transport_account) {
5894                 g_object_unref (store_account);
5895                 return FALSE;
5896         }
5897
5898         /* If the transport account was not used yet, then the send
5899            queue could not exist (it's created on demand) */
5900         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
5901         if (TNY_IS_SEND_QUEUE (send_queue))
5902                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
5903
5904         store_conn_status = tny_account_get_connection_status (store_account);
5905         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
5906                 gint response;
5907                 GtkWindow *toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) self);
5908
5909                 response = modest_platform_run_confirmation_dialog (toplevel,
5910                                                                     _("emev_nc_disconnect_account"));
5911                 if (response == GTK_RESPONSE_OK) {
5912                         retval = TRUE;
5913                 } else {
5914                         retval = FALSE;
5915                 }
5916         }
5917
5918         if (retval) {
5919
5920                 /* FIXME: We should only cancel those of this account */
5921                 modest_mail_operation_queue_cancel_all (queue);
5922
5923                 /* Also disconnect the account */
5924                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
5925                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
5926                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
5927                                                       FALSE, NULL, NULL);
5928                 }
5929                 if (sending) {
5930                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
5931                                                       FALSE, NULL, NULL);
5932                 }
5933         }
5934                 
5935         /* Frees */
5936         g_object_unref (store_account);
5937         g_object_unref (transport_account);
5938         
5939         return retval;
5940 }