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