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