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