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