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