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