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