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