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