4a207ac6ae6edc9c581783d3e4ec0c293651ca85
[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 (modest_runtime_get_conf (), 
2712                                                            G_OBJECT (header_view),
2713                                                            MODEST_CONF_HEADER_VIEW_KEY);
2714 #endif
2715                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2716                 }
2717         }
2718
2719         /* Update dimming state */
2720         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2721         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2722 }
2723
2724 void
2725 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2726                                      ModestWindow *win)
2727 {
2728         GtkWidget *dialog;
2729         gchar *txt, *item;
2730         gboolean online;
2731
2732         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2733
2734         online = tny_device_is_online (modest_runtime_get_device());
2735
2736         if (online) {
2737                 /* already online -- the item is simply not there... */
2738                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2739                                                  GTK_DIALOG_MODAL,
2740                                                  GTK_MESSAGE_WARNING,
2741                                                  GTK_BUTTONS_NONE,
2742                                                  _("The %s you selected cannot be found"),
2743                                                  item);
2744                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2745                 gtk_dialog_run (GTK_DIALOG(dialog));
2746         } else {
2747                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2748                                                       GTK_WINDOW (win),
2749                                                       GTK_DIALOG_MODAL,
2750                                                       _("mcen_bd_dialog_cancel"),
2751                                                       GTK_RESPONSE_REJECT,
2752                                                       _("mcen_bd_dialog_ok"),
2753                                                       GTK_RESPONSE_ACCEPT,
2754                                                       NULL);
2755                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2756                                          "Do you want to get online?"), item);
2757                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2758                                     gtk_label_new (txt), FALSE, FALSE, 0);
2759                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2760                 g_free (txt);
2761
2762                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2763                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2764                         /* TODO: Comment about why is this commented out: */
2765                         /* modest_platform_connect_and_wait (); */
2766                 }
2767         }
2768         gtk_widget_destroy (dialog);
2769 }
2770
2771 void
2772 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2773                                      ModestWindow *win)
2774 {
2775         /* g_message ("%s %s", __FUNCTION__, link); */
2776 }
2777
2778
2779 void
2780 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2781                                         ModestWindow *win)
2782 {
2783         modest_platform_activate_uri (link);
2784 }
2785
2786 void
2787 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2788                                           ModestWindow *win)
2789 {
2790         modest_platform_show_uri_popup (link);
2791 }
2792
2793 void
2794 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2795                                              ModestWindow *win)
2796 {
2797         /* we check for low-mem; in that case, show a warning, and don't allow
2798          * viewing attachments
2799          */
2800         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2801                 return;
2802
2803         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2804 }
2805
2806 void
2807 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2808                                           const gchar *address,
2809                                           ModestWindow *win)
2810 {
2811         /* g_message ("%s %s", __FUNCTION__, address); */
2812 }
2813
2814 static void
2815 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2816                       TnyMsg *saved_draft,
2817                       gpointer user_data)
2818 {
2819         ModestMsgEditWindow *edit_window;
2820
2821         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2822 #ifndef MODEST_TOOLKIT_HILDON2
2823         ModestMainWindow *win;
2824
2825         /* FIXME. Make the header view sensitive again. This is a
2826          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2827          * for details */
2828         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2829                                          modest_runtime_get_window_mgr(), FALSE));
2830         if (win != NULL) {
2831                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2832                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2833                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2834         }
2835 #endif
2836
2837         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2838
2839         /* Set draft is there was no error */
2840         if (!modest_mail_operation_get_error (mail_op))
2841                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2842
2843         g_object_unref(edit_window);
2844 }
2845
2846 static gboolean
2847 enough_space_for_message (ModestMsgEditWindow *edit_window,
2848                           MsgData *data)
2849 {
2850         guint64 available_disk, expected_size;
2851         gint parts_count;
2852         guint64 parts_size;
2853
2854         /* Check size */
2855         available_disk = modest_utils_get_available_space (NULL);
2856         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2857         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2858                                                       data->html_body,
2859                                                       parts_count,
2860                                                       parts_size);
2861
2862         /* Double check: memory full condition or message too big */
2863         if (available_disk < MIN_FREE_SPACE ||
2864             expected_size > available_disk) {
2865                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2866                 modest_platform_information_banner (NULL, NULL, msg);
2867                 g_free (msg);
2868
2869                 return FALSE;
2870         }
2871
2872         /*
2873          * djcb: if we're in low-memory state, we only allow for
2874          * saving messages smaller than
2875          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2876          * should still allow for sending anything critical...
2877          */
2878         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2879             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2880                 return FALSE;
2881
2882         /*
2883          * djcb: we also make sure that the attachments are smaller than the max size
2884          * this is for the case where we'd try to forward a message with attachments
2885          * bigger than our max allowed size, or sending an message from drafts which
2886          * somehow got past our checks when attaching.
2887          */
2888         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2889                 modest_platform_run_information_dialog (
2890                         GTK_WINDOW(edit_window),
2891                         _KR("memr_ib_operation_disabled"),
2892                         TRUE);
2893                 return FALSE;
2894         }
2895
2896         return TRUE;
2897 }
2898
2899 gboolean
2900 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2901 {
2902         TnyTransportAccount *transport_account;
2903         ModestMailOperation *mail_operation;
2904         MsgData *data;
2905         gchar *account_name;
2906         ModestAccountMgr *account_mgr;
2907         gboolean had_error = FALSE;
2908         ModestMainWindow *win = NULL;
2909
2910         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2911
2912         data = modest_msg_edit_window_get_msg_data (edit_window);
2913
2914         /* Check size */
2915         if (!enough_space_for_message (edit_window, data)) {
2916                 modest_msg_edit_window_free_msg_data (edit_window, data);
2917                 return FALSE;
2918         }
2919
2920         account_name = g_strdup (data->account_name);
2921         account_mgr = modest_runtime_get_account_mgr();
2922         if (!account_name)
2923                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2924         if (!account_name)
2925                 account_name = modest_account_mgr_get_default_account (account_mgr);
2926         if (!account_name) {
2927                 g_printerr ("modest: no account found\n");
2928                 modest_msg_edit_window_free_msg_data (edit_window, data);
2929                 return FALSE;
2930         }
2931
2932         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2933                 account_name = g_strdup (data->account_name);
2934         }
2935
2936         transport_account =
2937                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2938                                       (modest_runtime_get_account_store (),
2939                                        account_name,
2940                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2941         if (!transport_account) {
2942                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2943                 g_free (account_name);
2944                 modest_msg_edit_window_free_msg_data (edit_window, data);
2945                 return FALSE;
2946         }
2947
2948         /* Create the mail operation */
2949         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2950                                                                         NULL, NULL);
2951         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2952
2953         modest_mail_operation_save_to_drafts (mail_operation,
2954                                               transport_account,
2955                                               data->draft_msg,
2956                                               data->from,
2957                                               data->to, 
2958                                               data->cc, 
2959                                               data->bcc,
2960                                               data->subject,
2961                                               data->plain_body,
2962                                               data->html_body,
2963                                               data->attachments,
2964                                               data->images,
2965                                               data->priority_flags,
2966                                               data->references,
2967                                               data->in_reply_to,
2968                                               on_save_to_drafts_cb,
2969                                               g_object_ref(edit_window));
2970
2971 #ifdef MODEST_TOOLKIT_HILDON2
2972         /* In hildon2 we always show the information banner on saving to drafts.
2973          * It will be a system information banner in this case.
2974          */
2975         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2976         modest_platform_information_banner (NULL, NULL, text);
2977         g_free (text);
2978 #else
2979         /* Use the main window as the parent of the banner, if the
2980            main window does not exist it won't be shown, if the parent
2981            window exists then it's properly shown. We don't use the
2982            editor window because it could be closed (save to drafts
2983            could happen after closing the window */
2984         win = (ModestMainWindow *)
2985                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2986         if (win) {
2987                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2988                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2989                 g_free (text);
2990         }
2991 #endif
2992         modest_msg_edit_window_set_modified (edit_window, FALSE);
2993
2994         /* Frees */
2995         g_free (account_name);
2996         g_object_unref (G_OBJECT (transport_account));
2997         g_object_unref (G_OBJECT (mail_operation));
2998
2999         modest_msg_edit_window_free_msg_data (edit_window, data);
3000
3001         /* ** FIXME **
3002          * If the drafts folder is selected then make the header view
3003          * insensitive while the message is being saved to drafts
3004          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3005          * is not very clean but it avoids letting the drafts folder
3006          * in an inconsistent state: the user could edit the message
3007          * being saved and undesirable things would happen.
3008          * In the average case the user won't notice anything at
3009          * all. In the worst case (the user is editing a really big
3010          * file from Drafts) the header view will be insensitive
3011          * during the saving process (10 or 20 seconds, depending on
3012          * the message). Anyway this is just a quick workaround: once
3013          * we find a better solution it should be removed
3014          * See NB#65125 (commend #18) for details.
3015          */
3016         if (!had_error && win != NULL) {
3017                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3018                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3019                 if (view != NULL) {
3020                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3021                         if (folder) {
3022                                 if (modest_tny_folder_is_local_folder(folder)) {
3023                                         TnyFolderType folder_type;
3024                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3025                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3026                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3027                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3028                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3029                                         }
3030                                 }
3031                         }
3032                         if (folder != NULL) g_object_unref(folder);
3033                 }
3034         }
3035
3036         return !had_error;
3037 }
3038
3039 /* For instance, when clicking the Send toolbar button when editing a message: */
3040 gboolean
3041 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3042 {
3043         TnyTransportAccount *transport_account = NULL;
3044         gboolean had_error = FALSE;
3045         MsgData *data;
3046         ModestAccountMgr *account_mgr;
3047         gchar *account_name;
3048         ModestMailOperation *mail_operation;
3049
3050         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3051
3052         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3053                 return TRUE;
3054
3055         data = modest_msg_edit_window_get_msg_data (edit_window);
3056
3057         /* Check size */
3058         if (!enough_space_for_message (edit_window, data)) {
3059                 modest_msg_edit_window_free_msg_data (edit_window, data);
3060                 return FALSE;
3061         }
3062
3063         account_mgr = modest_runtime_get_account_mgr();
3064         account_name = g_strdup (data->account_name);
3065         if (!account_name)
3066                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3067
3068         if (!account_name)
3069                 account_name = modest_account_mgr_get_default_account (account_mgr);
3070
3071         if (!account_name) {
3072                 modest_msg_edit_window_free_msg_data (edit_window, data);
3073                 /* Run account setup wizard */
3074                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3075                         return TRUE;
3076                 }
3077         }
3078
3079         /* Get the currently-active transport account for this modest account: */
3080         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3081                 transport_account =
3082                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3083                                               (modest_runtime_get_account_store (),
3084                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3085         }
3086
3087         if (!transport_account) {
3088                 modest_msg_edit_window_free_msg_data (edit_window, data);
3089                 /* Run account setup wizard */
3090                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3091                         return TRUE;
3092         }
3093
3094
3095         /* Create the mail operation */
3096         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3097         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3098
3099         modest_mail_operation_send_new_mail (mail_operation,
3100                                              transport_account,
3101                                              data->draft_msg,
3102                                              data->from,
3103                                              data->to,
3104                                              data->cc,
3105                                              data->bcc,
3106                                              data->subject,
3107                                              data->plain_body,
3108                                              data->html_body,
3109                                              data->attachments,
3110                                              data->images,
3111                                              data->references,
3112                                              data->in_reply_to,
3113                                              data->priority_flags);
3114
3115         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3116                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3117
3118         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3119                 const GError *error = modest_mail_operation_get_error (mail_operation);
3120                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3121                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3122                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3123                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3124                         had_error = TRUE;
3125                 }
3126         }
3127
3128         /* Free data: */
3129         g_free (account_name);
3130         g_object_unref (G_OBJECT (transport_account));
3131         g_object_unref (G_OBJECT (mail_operation));
3132
3133         modest_msg_edit_window_free_msg_data (edit_window, data);
3134
3135         if (!had_error) {
3136                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3137
3138                 /* Save settings and close the window: */
3139                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3140         }
3141
3142         return !had_error;
3143 }
3144
3145 void
3146 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3147                                   ModestMsgEditWindow *window)
3148 {
3149         ModestMsgEditFormatState *format_state = NULL;
3150
3151         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3152         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3153
3154         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3155                 return;
3156
3157         format_state = modest_msg_edit_window_get_format_state (window);
3158         g_return_if_fail (format_state != NULL);
3159
3160         format_state->bold = gtk_toggle_action_get_active (action);
3161         modest_msg_edit_window_set_format_state (window, format_state);
3162         g_free (format_state);
3163
3164 }
3165
3166 void
3167 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3168                                      ModestMsgEditWindow *window)
3169 {
3170         ModestMsgEditFormatState *format_state = NULL;
3171
3172         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3173         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3174
3175         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3176                 return;
3177
3178         format_state = modest_msg_edit_window_get_format_state (window);
3179         g_return_if_fail (format_state != NULL);
3180
3181         format_state->italics = gtk_toggle_action_get_active (action);
3182         modest_msg_edit_window_set_format_state (window, format_state);
3183         g_free (format_state);
3184
3185 }
3186
3187 void
3188 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3189                                      ModestMsgEditWindow *window)
3190 {
3191         ModestMsgEditFormatState *format_state = NULL;
3192
3193         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3194         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3195
3196         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3197                 return;
3198
3199         format_state = modest_msg_edit_window_get_format_state (window);
3200         g_return_if_fail (format_state != NULL);
3201
3202         format_state->bullet = gtk_toggle_action_get_active (action);
3203         modest_msg_edit_window_set_format_state (window, format_state);
3204         g_free (format_state);
3205
3206 }
3207
3208 void
3209 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3210                                      GtkRadioAction *selected,
3211                                      ModestMsgEditWindow *window)
3212 {
3213         ModestMsgEditFormatState *format_state = NULL;
3214         GtkJustification value;
3215
3216         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3217
3218         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3219                 return;
3220
3221         value = gtk_radio_action_get_current_value (selected);
3222
3223         format_state = modest_msg_edit_window_get_format_state (window);
3224         g_return_if_fail (format_state != NULL);
3225
3226         format_state->justification = value;
3227         modest_msg_edit_window_set_format_state (window, format_state);
3228         g_free (format_state);
3229 }
3230
3231 void
3232 modest_ui_actions_on_select_editor_color (GtkAction *action,
3233                                           ModestMsgEditWindow *window)
3234 {
3235         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3236         g_return_if_fail (GTK_IS_ACTION (action));
3237
3238         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3239                 return;
3240
3241         modest_msg_edit_window_select_color (window);
3242 }
3243
3244 void
3245 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3246                                                      ModestMsgEditWindow *window)
3247 {
3248         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3249         g_return_if_fail (GTK_IS_ACTION (action));
3250
3251         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3252                 return;
3253
3254         modest_msg_edit_window_select_background_color (window);
3255 }
3256
3257 void
3258 modest_ui_actions_on_insert_image (GObject *object,
3259                                    ModestMsgEditWindow *window)
3260 {
3261         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3262
3263
3264         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3265                 return;
3266
3267         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3268                 return;
3269
3270         modest_msg_edit_window_insert_image (window);
3271 }
3272
3273 void
3274 modest_ui_actions_on_attach_file (GtkAction *action,
3275                                   ModestMsgEditWindow *window)
3276 {
3277         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3278         g_return_if_fail (GTK_IS_ACTION (action));
3279
3280         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3281                 return;
3282
3283         modest_msg_edit_window_offer_attach_file (window);
3284 }
3285
3286 void
3287 modest_ui_actions_on_remove_attachments (GtkAction *action,
3288                                          ModestMsgEditWindow *window)
3289 {
3290         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3291
3292         modest_msg_edit_window_remove_attachments (window, NULL);
3293 }
3294
3295 static void
3296 do_create_folder_cb (ModestMailOperation *mail_op,
3297                      TnyFolderStore *parent_folder,
3298                      TnyFolder *new_folder,
3299                      gpointer user_data)
3300 {
3301         gchar *suggested_name = (gchar *) user_data;
3302         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3303         const GError *error;
3304
3305         error = modest_mail_operation_get_error (mail_op);
3306         if (error) {
3307
3308                 /* Show an error. If there was some problem writing to
3309                    disk, show it, otherwise show the generic folder
3310                    create error. We do it here and not in an error
3311                    handler because the call to do_create_folder will
3312                    stop the main loop in a gtk_dialog_run and then,
3313                    the message won't be shown until that dialog is
3314                    closed */
3315                 modest_ui_actions_disk_operations_error_handler (mail_op,
3316                                                                  _("mail_in_ui_folder_create_error"));
3317
3318                 if (!is_memory_full_error ((GError *) error, mail_op)) {
3319                         /* Try again if there is no full memory condition */
3320                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3321                 }
3322         } else {
3323                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3324                  * FIXME: any other? */
3325                 GtkWidget *folder_view;
3326
3327                 if (MODEST_IS_MAIN_WINDOW(source_win))
3328                         folder_view =
3329                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3330                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3331                 else
3332                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3333                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3334
3335                 /* Select the newly created folder. It could happen
3336                    that the widget is no longer there (i.e. the window
3337                    has been destroyed, so we need to check this */
3338                 if (folder_view)
3339                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3340                                                           new_folder, FALSE);
3341                 g_object_unref (new_folder);
3342         }
3343         /* Free. Note that the first time it'll be NULL so noop */
3344         g_free (suggested_name);
3345         g_object_unref (source_win);
3346 }
3347
3348 typedef struct {
3349         gchar *folder_name;
3350         TnyFolderStore *parent;
3351 } CreateFolderConnect;
3352
3353 static void
3354 do_create_folder_performer (gboolean canceled,
3355                          GError *err,
3356                          GtkWindow *parent_window,
3357                          TnyAccount *account,
3358                          gpointer user_data)
3359 {
3360         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3361         ModestMailOperation *mail_op;
3362
3363         if (canceled || err) {
3364                 /* In memory full conditions we could get this error here */
3365                 check_memory_full_error ((GtkWidget *) parent_window, err);
3366
3367                 /* This happens if we have selected the outbox folder
3368                    as the parent */
3369                 if (err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3370                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3371                         /* Show an error and retry */
3372                         modest_platform_information_banner ((GtkWidget *) parent_window,
3373                                                             NULL,
3374                                                             _("mail_in_ui_folder_create_error"));
3375
3376                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3377                 }
3378
3379                 goto frees;
3380         }
3381
3382         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3383         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3384                                          mail_op);
3385         modest_mail_operation_create_folder (mail_op,
3386                                              helper->parent,
3387                                              (const gchar *) helper->folder_name,
3388                                              do_create_folder_cb,
3389                                              g_strdup (helper->folder_name));
3390         g_object_unref (mail_op);
3391
3392  frees:
3393         if (helper->parent)
3394                 g_object_unref (helper->parent);
3395         if (helper->folder_name)
3396                 g_free (helper->folder_name);
3397         g_slice_free (CreateFolderConnect, helper);
3398 }
3399
3400
3401 static void
3402 do_create_folder (GtkWindow *parent_window,
3403                   TnyFolderStore *suggested_parent,
3404                   const gchar *suggested_name)
3405 {
3406         gint result;
3407         gchar *folder_name = NULL;
3408         TnyFolderStore *parent_folder = NULL;
3409
3410         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3411                                                         suggested_parent,
3412                                                         (gchar *) suggested_name,
3413                                                         &folder_name,
3414                                                         &parent_folder);
3415
3416         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3417                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3418                 helper->folder_name = g_strdup (folder_name);
3419                 helper->parent = g_object_ref (parent_folder);
3420
3421                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3422                                                                TRUE,
3423                                                                parent_folder,
3424                                                                do_create_folder_performer,
3425                                                                helper);
3426         }
3427
3428         if (folder_name)
3429                 g_free (folder_name);
3430         if (parent_folder)
3431                 g_object_unref (parent_folder);
3432 }
3433
3434 static void
3435 modest_ui_actions_create_folder(GtkWidget *parent_window,
3436                                 GtkWidget *folder_view,
3437                                 TnyFolderStore *parent_folder)
3438 {
3439         if (!parent_folder) {
3440 #ifdef MODEST_TOOLKIT_HILDON2
3441                 ModestTnyAccountStore *acc_store;
3442
3443                 acc_store = modest_runtime_get_account_store ();
3444
3445                 parent_folder = (TnyFolderStore *)
3446                         modest_tny_account_store_get_local_folders_account (acc_store);
3447 #else
3448                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3449 #endif
3450         }
3451
3452         if (parent_folder) {
3453                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3454                 g_object_unref (parent_folder);
3455         }
3456 }
3457
3458 void
3459 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3460 {
3461
3462         g_return_if_fail (MODEST_IS_WINDOW(window));
3463
3464         if (MODEST_IS_MAIN_WINDOW (window)) {
3465                 GtkWidget *folder_view;
3466
3467                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3468                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3469                 if (!folder_view)
3470                         return;
3471
3472                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3473 #ifdef MODEST_TOOLKIT_HILDON2
3474         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3475                 GtkWidget *folder_view;
3476
3477                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3478                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3479 #endif
3480         } else {
3481                 g_assert_not_reached ();
3482         }
3483 }
3484
3485 static void
3486 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3487                                                gpointer user_data)
3488 {
3489         const GError *error = NULL;
3490         gchar *message = NULL;
3491         gboolean mem_full;
3492
3493         /* Get error message */
3494         error = modest_mail_operation_get_error (mail_op);
3495         if (!error)
3496                 g_return_if_reached ();
3497
3498         mem_full = is_memory_full_error ((GError *) error, mail_op);
3499         if (mem_full) {
3500                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3501         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3502                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3503                 message = _CS("ckdg_ib_folder_already_exists");
3504         } else if (error->domain == TNY_ERROR_DOMAIN &&
3505                    error->code == TNY_SERVICE_ERROR_STATE) {
3506                 /* This means that the folder is already in use (a
3507                    message is opened for example */
3508                 message = _("emev_ni_internal_error");
3509         } else {
3510                 message = _CS("ckdg_ib_unable_to_rename");
3511         }
3512
3513         /* We don't set a parent for the dialog because the dialog
3514            will be destroyed so the banner won't appear */
3515         modest_platform_information_banner (NULL, NULL, message);
3516
3517         if (mem_full)
3518                 g_free (message);
3519 }
3520
3521 typedef struct {
3522         TnyFolderStore *folder;
3523         gchar *new_name;
3524 } RenameFolderInfo;
3525
3526 static void
3527 on_rename_folder_cb (ModestMailOperation *mail_op,
3528                      TnyFolder *new_folder,
3529                      gpointer user_data)
3530 {
3531         ModestFolderView *folder_view;
3532
3533         /* If the window was closed when renaming a folder, or if
3534          * it's not a main window this will happen */
3535         if (!MODEST_IS_FOLDER_VIEW (user_data))
3536                 return;
3537
3538         folder_view = MODEST_FOLDER_VIEW (user_data);
3539         /* Note that if the rename fails new_folder will be NULL */
3540         if (new_folder) {
3541                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3542         } else {
3543                 modest_folder_view_select_first_inbox_or_local (folder_view);
3544         }
3545         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3546 }
3547
3548 static void
3549 on_rename_folder_performer (gboolean canceled,
3550                             GError *err,
3551                             GtkWindow *parent_window,
3552                             TnyAccount *account,
3553                             gpointer user_data)
3554 {
3555         ModestMailOperation *mail_op = NULL;
3556         GtkTreeSelection *sel = NULL;
3557         GtkWidget *folder_view = NULL;
3558         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3559
3560         if (canceled || err) {
3561                 /* In memory full conditions we could get this error here */
3562                 check_memory_full_error ((GtkWidget *) parent_window, err);
3563         } else {
3564
3565                 mail_op =
3566                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3567                                         modest_ui_actions_rename_folder_error_handler,
3568                                         parent_window, NULL);
3569
3570                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3571                                 mail_op);
3572
3573                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3574
3575                         folder_view = modest_main_window_get_child_widget (
3576                                 MODEST_MAIN_WINDOW (parent_window),
3577                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3578                 }
3579 #ifdef MODEST_TOOLKIT_HILDON2
3580                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3581                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3582                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3583                 }
3584 #endif
3585
3586                 /* Clear the folders view */
3587                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3588                 gtk_tree_selection_unselect_all (sel);
3589
3590                 /* Actually rename the folder */
3591                 modest_mail_operation_rename_folder (mail_op,
3592                                                      TNY_FOLDER (data->folder),
3593                                                      (const gchar *) (data->new_name),
3594                                                      on_rename_folder_cb,
3595                                                      folder_view);
3596                 g_object_unref (mail_op);
3597         }
3598
3599         g_object_unref (data->folder);
3600         g_free (data->new_name);
3601         g_free (data);
3602 }
3603
3604 void
3605 modest_ui_actions_on_rename_folder (GtkAction *action,
3606                                      ModestWindow *window)
3607 {
3608         modest_ui_actions_on_edit_mode_rename_folder (window);
3609 }
3610
3611 gboolean
3612 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3613 {
3614         TnyFolderStore *folder;
3615         GtkWidget *folder_view;
3616         gboolean do_rename = TRUE;
3617
3618         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3619
3620         if (MODEST_IS_MAIN_WINDOW (window)) {
3621                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3622                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3623                 if (!folder_view)
3624                         return FALSE;
3625
3626 #ifdef MODEST_TOOLKIT_HILDON2
3627         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3628                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3629 #endif
3630         } else {
3631                 return FALSE;
3632         }
3633
3634         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3635
3636         if (!folder)
3637                 return FALSE;
3638
3639         if (TNY_IS_FOLDER (folder)) {
3640                 gchar *folder_name = NULL;
3641                 gint response;
3642                 const gchar *current_name;
3643                 TnyFolderStore *parent;
3644
3645                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3646                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3647                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3648                                                                      parent, current_name,
3649                                                                      &folder_name);
3650                 g_object_unref (parent);
3651
3652                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3653                         do_rename = FALSE;
3654                 } else {
3655                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3656                         rename_folder_data->folder = g_object_ref (folder);
3657                         rename_folder_data->new_name = folder_name;
3658                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3659                                         folder, on_rename_folder_performer, rename_folder_data);
3660                 }
3661         }
3662         g_object_unref (folder);
3663         return do_rename;
3664 }
3665
3666 static void
3667 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3668                                                gpointer user_data)
3669 {
3670         GObject *win = modest_mail_operation_get_source (mail_op);
3671
3672         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3673                                                 _("mail_in_ui_folder_delete_error"),
3674                                                 FALSE);
3675         g_object_unref (win);
3676 }
3677
3678 typedef struct {
3679         TnyFolderStore *folder;
3680         gboolean move_to_trash;
3681 } DeleteFolderInfo;
3682
3683 static void
3684 on_delete_folder_cb (gboolean canceled,
3685                   GError *err,
3686                   GtkWindow *parent_window,
3687                   TnyAccount *account,
3688                   gpointer user_data)
3689 {
3690         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3691         GtkWidget *folder_view;
3692         ModestMailOperation *mail_op;
3693         GtkTreeSelection *sel;
3694
3695         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3696                 g_object_unref (G_OBJECT (info->folder));
3697                 g_free (info);
3698                 return;
3699         }
3700
3701         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3702                 folder_view = modest_main_window_get_child_widget (
3703                         MODEST_MAIN_WINDOW (parent_window),
3704                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3705 #ifdef MODEST_TOOLKIT_HILDON2
3706         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3707                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3708 #endif
3709         } else {
3710                 g_object_unref (G_OBJECT (info->folder));
3711                 g_free (info);
3712                 return;
3713         }
3714
3715         /* Unselect the folder before deleting it to free the headers */
3716         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3717         gtk_tree_selection_unselect_all (sel);
3718
3719         /* Create the mail operation */
3720         mail_op =
3721                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3722                                 modest_ui_actions_delete_folder_error_handler,
3723                                 NULL, NULL);
3724
3725         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3726                         mail_op);
3727         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3728
3729         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3730
3731         g_object_unref (G_OBJECT (mail_op));
3732         g_object_unref (G_OBJECT (info->folder));
3733         g_free (info);
3734 }
3735
3736 static gboolean
3737 delete_folder (ModestWindow *window, gboolean move_to_trash)
3738 {
3739         TnyFolderStore *folder;
3740         GtkWidget *folder_view;
3741         gint response;
3742         gchar *message;
3743
3744         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3745
3746         if (MODEST_IS_MAIN_WINDOW (window)) {
3747
3748                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3749                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3750 #ifdef MODEST_TOOLKIT_HILDON2
3751         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3752                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3753 #endif
3754         } else {
3755                 return FALSE;
3756         }
3757         if (!folder_view)
3758                 return FALSE;
3759
3760         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3761
3762         if (!folder)
3763                 return FALSE;
3764
3765         /* Show an error if it's an account */
3766         if (!TNY_IS_FOLDER (folder)) {
3767                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3768                                                         _("mail_in_ui_folder_delete_error"),
3769                                                         FALSE);
3770                 g_object_unref (G_OBJECT (folder));
3771                 return FALSE;
3772         }
3773
3774         /* Ask the user */
3775         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3776                                     tny_folder_get_name (TNY_FOLDER (folder)));
3777         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3778                                                             (const gchar *) message);
3779         g_free (message);
3780
3781         if (response == GTK_RESPONSE_OK) {
3782                 DeleteFolderInfo *info;
3783                 info = g_new0(DeleteFolderInfo, 1);
3784                 info->folder = folder;
3785                 info->move_to_trash = move_to_trash;
3786                 g_object_ref (G_OBJECT (info->folder));
3787                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3788                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3789                                                                TRUE,
3790                                                                TNY_FOLDER_STORE (account),
3791                                                                on_delete_folder_cb, info);
3792                 g_object_unref (account);
3793                 return TRUE;
3794         } else {
3795                 return FALSE;
3796         }
3797         g_object_unref (G_OBJECT (folder));
3798 }
3799
3800 void
3801 modest_ui_actions_on_delete_folder (GtkAction *action,
3802                                     ModestWindow *window)
3803 {
3804         modest_ui_actions_on_edit_mode_delete_folder (window);
3805 }
3806
3807 gboolean
3808 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3809 {
3810         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3811
3812         return delete_folder (window, FALSE);
3813 }
3814
3815 void
3816 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3817 {
3818         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3819
3820         delete_folder (MODEST_WINDOW (main_window), TRUE);
3821 }
3822
3823
3824 typedef struct _PasswordDialogFields {
3825         GtkWidget *username;
3826         GtkWidget *password;
3827         GtkWidget *dialog;
3828 } PasswordDialogFields;
3829
3830 static void
3831 password_dialog_check_field (GtkEditable *editable,
3832                              PasswordDialogFields *fields)
3833 {
3834         const gchar *value;
3835         gboolean any_value_empty = FALSE;
3836
3837 #ifdef MODEST_TOOLKIT_HILDON2
3838         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3839 #else
3840         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3841 #endif
3842         if ((value == NULL) || value[0] == '\0') {
3843                 any_value_empty = TRUE;
3844         }
3845 #ifdef MODEST_TOOLKIT_HILDON2
3846         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3847 #else
3848         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3849 #endif
3850         if ((value == NULL) || value[0] == '\0') {
3851                 any_value_empty = TRUE;
3852         }
3853         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3854 }
3855
3856 void
3857 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3858                                          const gchar* server_account_name,
3859                                          gchar **username,
3860                                          gchar **password,
3861                                          gboolean *cancel,
3862                                          gboolean *remember,
3863                                          ModestMainWindow *main_window)
3864 {
3865         g_return_if_fail(server_account_name);
3866         gboolean completed = FALSE;
3867         PasswordDialogFields *fields = NULL;
3868
3869         /* Initalize output parameters: */
3870         if (cancel)
3871                 *cancel = FALSE;
3872
3873         if (remember)
3874                 *remember = TRUE;
3875
3876 #ifndef MODEST_TOOLKIT_GTK
3877         /* Maemo uses a different (awkward) button order,
3878          * It should probably just use gtk_alternative_dialog_button_order ().
3879          */
3880 #ifdef MODEST_TOOLKIT_HILDON2
3881         GtkWidget *dialog =
3882                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3883                                              NULL,
3884                                              GTK_DIALOG_MODAL,
3885                                              _HL("wdgt_bd_done"),
3886                                              GTK_RESPONSE_ACCEPT,
3887                                              NULL);
3888         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3889                                         HILDON_MARGIN_DOUBLE);
3890 #else
3891         GtkWidget *dialog =
3892                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3893                                              NULL,
3894                                              GTK_DIALOG_MODAL,
3895                                              _("mcen_bd_dialog_ok"),
3896                                              GTK_RESPONSE_ACCEPT,
3897                                              _("mcen_bd_dialog_cancel"),
3898                                              GTK_RESPONSE_REJECT,
3899                                              NULL);
3900 #endif /* MODEST_TOOLKIT_HILDON2 */
3901 #else
3902         GtkWidget *dialog =
3903                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3904                                              NULL,
3905                                              GTK_DIALOG_MODAL,
3906                                              GTK_STOCK_CANCEL,
3907                                              GTK_RESPONSE_REJECT,
3908                                              GTK_STOCK_OK,
3909                                              GTK_RESPONSE_ACCEPT,
3910                                              NULL);
3911 #endif /* MODEST_TOOLKIT_GTK */
3912
3913         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3914
3915         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3916                 modest_runtime_get_account_mgr(), server_account_name);
3917         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3918                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3919                 if (cancel)
3920                         *cancel = TRUE;
3921                 gtk_widget_destroy (dialog);
3922                 return;
3923         }
3924
3925         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3926         GtkWidget *label = gtk_label_new (txt);
3927         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3928         g_free (txt);
3929         g_free (server_name);
3930         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3931                             FALSE, FALSE, 0);
3932         server_name = NULL;
3933
3934         /* username: */
3935         gchar *initial_username = modest_account_mgr_get_server_account_username (
3936                 modest_runtime_get_account_mgr(), server_account_name);
3937
3938 #ifdef MODEST_TOOLKIT_HILDON2
3939         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3940         if (initial_username)
3941                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
3942 #else
3943         GtkWidget *entry_username = gtk_entry_new ();
3944         if (initial_username)
3945                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3946 #endif
3947         /* Dim this if a connection has ever succeeded with this username,
3948          * as per the UI spec: */
3949         /* const gboolean username_known =  */
3950         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3951         /*              modest_runtime_get_account_mgr(), server_account_name); */
3952         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3953
3954         /* We drop the username sensitive code and disallow changing it here
3955          * as tinymail does not support really changing the username in the callback
3956          */
3957         gtk_widget_set_sensitive (entry_username, FALSE);
3958
3959 #ifndef MODEST_TOOLKIT_GTK
3960         /* Auto-capitalization is the default, so let's turn it off: */
3961         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3962
3963         /* Create a size group to be used by all captions.
3964          * Note that HildonCaption does not create a default size group if we do not specify one.
3965          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3966         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3967
3968 #ifdef MODEST_TOOLKIT_HILDON2
3969         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3970                                                                   _("mail_fi_username"), FALSE,
3971                                                                   entry_username);
3972 #else
3973         GtkWidget *caption = hildon_caption_new (sizegroup,
3974                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3975 #endif
3976         gtk_widget_show (entry_username);
3977         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3978                 FALSE, FALSE, MODEST_MARGIN_HALF);
3979         gtk_widget_show (caption);
3980 #else
3981         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3982                             TRUE, FALSE, 0);
3983 #endif /* !MODEST_TOOLKIT_GTK */
3984
3985         /* password: */
3986 #ifdef MODEST_TOOLKIT_HILDON2
3987         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3988 #else
3989         GtkWidget *entry_password = gtk_entry_new ();
3990 #endif
3991         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3992         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3993
3994 #ifndef MODEST_TOOLKIT_GTK
3995         /* Auto-capitalization is the default, so let's turn it off: */
3996         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3997                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3998
3999 #ifdef MODEST_TOOLKIT_HILDON2
4000         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4001                                                        _("mail_fi_password"), FALSE,
4002                                                        entry_password);
4003 #else
4004         caption = hildon_caption_new (sizegroup,
4005                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4006 #endif
4007         gtk_widget_show (entry_password);
4008         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4009                 FALSE, FALSE, MODEST_MARGIN_HALF);
4010         gtk_widget_show (caption);
4011         g_object_unref (sizegroup);
4012 #else
4013         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4014                             TRUE, FALSE, 0);
4015 #endif /* !MODEST_TOOLKIT_GTK */
4016
4017         if (initial_username != NULL)
4018                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4019
4020 /* This is not in the Maemo UI spec:
4021         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4022         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4023                             TRUE, FALSE, 0);
4024 */
4025
4026         fields = g_slice_new0 (PasswordDialogFields);
4027         fields->username = entry_username;
4028         fields->password = entry_password;
4029         fields->dialog = dialog;
4030
4031         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4032         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4033         password_dialog_check_field (NULL, fields);
4034
4035         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4036
4037         while (!completed) {
4038
4039                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4040                         if (username) {
4041 #ifdef MODEST_TOOLKIT_HILDON2
4042                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4043 #else
4044                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4045 #endif
4046
4047                                 /* Note that an empty field becomes the "" string */
4048                                 if (*username && strlen (*username) > 0) {
4049                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4050                                                                                         server_account_name,
4051                                                                                         *username);
4052                                         completed = TRUE;
4053
4054                                         const gboolean username_was_changed =
4055                                                 (strcmp (*username, initial_username) != 0);
4056                                         if (username_was_changed) {
4057                                                 g_warning ("%s: tinymail does not yet support changing the "
4058                                                            "username in the get_password() callback.\n", __FUNCTION__);
4059                                         }
4060                                 } else {
4061                                         g_free (*username);
4062                                         *username = NULL;
4063                                         /* Show error */
4064                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4065                                                                             _("mcen_ib_username_pw_incorrect"));
4066                                         completed = FALSE;
4067                                 }
4068                         }
4069
4070                         if (password) {
4071 #ifdef MODEST_TOOLKIT_HILDON2
4072                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4073 #else
4074                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4075 #endif
4076
4077                                 /* We do not save the password in the configuration,
4078                                  * because this function is only called for passwords that should
4079                                  * not be remembered:
4080                                  modest_server_account_set_password (
4081                                  modest_runtime_get_account_mgr(), server_account_name,
4082                                  *password);
4083                                  */
4084                         }
4085                         if (cancel)
4086                                 *cancel   = FALSE;
4087                 } else {
4088 #ifndef MODEST_TOOLKIT_HILDON2
4089                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4090                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4091 #endif
4092                         completed = TRUE;
4093                         if (username)
4094                                 *username = NULL;
4095                         if (password)
4096                                 *password = NULL;
4097                         if (cancel)
4098                                 *cancel   = TRUE;
4099                 }
4100         }
4101
4102 /* This is not in the Maemo UI spec:
4103         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4104                 *remember = TRUE;
4105         else
4106                 *remember = FALSE;
4107 */
4108
4109         g_free (initial_username);
4110         gtk_widget_destroy (dialog);
4111         g_slice_free (PasswordDialogFields, fields);
4112
4113         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4114 }
4115
4116 void
4117 modest_ui_actions_on_cut (GtkAction *action,
4118                           ModestWindow *window)
4119 {
4120         GtkWidget *focused_widget;
4121         GtkClipboard *clipboard;
4122
4123         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4124         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4125         if (GTK_IS_EDITABLE (focused_widget)) {
4126                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4127                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4128                 gtk_clipboard_store (clipboard);
4129         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4130                 GtkTextBuffer *buffer;
4131
4132                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4133                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4134                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4135                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4136                         gtk_clipboard_store (clipboard);
4137                 }
4138         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4139                 TnyList *header_list = modest_header_view_get_selected_headers (
4140                                 MODEST_HEADER_VIEW (focused_widget));
4141                 gboolean continue_download = FALSE;
4142                 gint num_of_unc_msgs;
4143
4144                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4145
4146                 if (num_of_unc_msgs) {
4147                         TnyAccount *account = get_account_from_header_list (header_list);
4148                         if (account) {
4149                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4150                                 g_object_unref (account);
4151                         }
4152                 }
4153
4154                 if (num_of_unc_msgs == 0 || continue_download) {
4155 /*                      modest_platform_information_banner (
4156                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4157                         modest_header_view_cut_selection (
4158                                         MODEST_HEADER_VIEW (focused_widget));
4159                 }
4160
4161                 g_object_unref (header_list);
4162         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4163                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4164         }
4165 }
4166
4167 void
4168 modest_ui_actions_on_copy (GtkAction *action,
4169                            ModestWindow *window)
4170 {
4171         GtkClipboard *clipboard;
4172         GtkWidget *focused_widget;
4173         gboolean copied = TRUE;
4174
4175         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4176         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4177
4178         if (GTK_IS_LABEL (focused_widget)) {
4179                 gchar *selection;
4180                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4181                 gtk_clipboard_set_text (clipboard, selection, -1);
4182                 g_free (selection);
4183                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4184                 gtk_clipboard_store (clipboard);
4185         } else if (GTK_IS_EDITABLE (focused_widget)) {
4186                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4187                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4188                 gtk_clipboard_store (clipboard);
4189         } else if (GTK_IS_HTML (focused_widget)) {
4190                 const gchar *sel;
4191                 int len = -1;
4192                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4193                 if ((sel == NULL) || (sel[0] == '\0')) {
4194                         copied = FALSE;
4195                 } else {
4196                         gtk_html_copy (GTK_HTML (focused_widget));
4197                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4198                         gtk_clipboard_store (clipboard);
4199                 }
4200         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4201                 GtkTextBuffer *buffer;
4202                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4203                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4204                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4205                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4206                         gtk_clipboard_store (clipboard);
4207                 }
4208         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4209                 TnyList *header_list = modest_header_view_get_selected_headers (
4210                                 MODEST_HEADER_VIEW (focused_widget));
4211                 gboolean continue_download = FALSE;
4212                 gint num_of_unc_msgs;
4213
4214                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4215
4216                 if (num_of_unc_msgs) {
4217                         TnyAccount *account = get_account_from_header_list (header_list);
4218                         if (account) {
4219                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4220                                 g_object_unref (account);
4221                         }
4222                 }
4223
4224                 if (num_of_unc_msgs == 0 || continue_download) {
4225                         modest_platform_information_banner (
4226                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4227                         modest_header_view_copy_selection (
4228                                         MODEST_HEADER_VIEW (focused_widget));
4229                 } else
4230                         copied = FALSE;
4231
4232                 g_object_unref (header_list);
4233
4234         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4235                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4236         }
4237
4238         /* Show information banner if there was a copy to clipboard */
4239         if(copied)
4240                 modest_platform_information_banner (
4241                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4242 }
4243
4244 void
4245 modest_ui_actions_on_undo (GtkAction *action,
4246                            ModestWindow *window)
4247 {
4248         ModestEmailClipboard *clipboard = NULL;
4249
4250         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4251                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4252         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4253                 /* Clear clipboard source */
4254                 clipboard = modest_runtime_get_email_clipboard ();
4255                 modest_email_clipboard_clear (clipboard);
4256         }
4257         else {
4258                 g_return_if_reached ();
4259         }
4260 }
4261
4262 void
4263 modest_ui_actions_on_redo (GtkAction *action,
4264                            ModestWindow *window)
4265 {
4266         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4267                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4268         }
4269         else {
4270                 g_return_if_reached ();
4271         }
4272 }
4273
4274
4275 static void
4276 destroy_information_note (ModestMailOperation *mail_op,
4277                           gpointer user_data)
4278 {
4279         /* destroy information note */
4280         gtk_widget_destroy (GTK_WIDGET(user_data));
4281 }
4282
4283 static void
4284 destroy_folder_information_note (ModestMailOperation *mail_op,
4285                                  TnyFolder *new_folder,
4286                                  gpointer user_data)
4287 {
4288         /* destroy information note */
4289         gtk_widget_destroy (GTK_WIDGET(user_data));
4290 }
4291
4292
4293 static void
4294 paste_as_attachment_free (gpointer data)
4295 {
4296         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4297
4298         if (helper->banner) {
4299                 gtk_widget_destroy (helper->banner);
4300                 g_object_unref (helper->banner);
4301         }
4302         g_free (helper);
4303 }
4304
4305 static void
4306 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4307                             TnyHeader *header,
4308                             TnyMsg *msg,
4309                             gpointer userdata)
4310 {
4311         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4312         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4313
4314         if (msg == NULL)
4315                 return;
4316
4317         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4318
4319 }
4320
4321 void
4322 modest_ui_actions_on_paste (GtkAction *action,
4323                             ModestWindow *window)
4324 {
4325         GtkWidget *focused_widget = NULL;
4326         GtkWidget *inf_note = NULL;
4327         ModestMailOperation *mail_op = NULL;
4328
4329         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4330         if (GTK_IS_EDITABLE (focused_widget)) {
4331                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4332         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4333                 ModestEmailClipboard *e_clipboard = NULL;
4334                 e_clipboard = modest_runtime_get_email_clipboard ();
4335                 if (modest_email_clipboard_cleared (e_clipboard)) {
4336                         GtkTextBuffer *buffer;
4337                         GtkClipboard *clipboard;
4338
4339                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4340                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4341                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4342                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4343                         ModestMailOperation *mail_op;
4344                         TnyFolder *src_folder = NULL;
4345                         TnyList *data = NULL;
4346                         gboolean delete;
4347                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4348                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4349                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4350                                                                            _CS("ckct_nw_pasting"));
4351                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4352                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4353                         if (helper->banner != NULL) {
4354                                 g_object_ref (G_OBJECT (helper->banner));
4355                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4356                         }
4357
4358                         if (data != NULL) {
4359                                 modest_mail_operation_get_msgs_full (mail_op,
4360                                                                      data,
4361                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4362                                                                      helper,
4363                                                                      paste_as_attachment_free);
4364                         }
4365                         /* Free */
4366                         if (data)
4367                                 g_object_unref (data);
4368                         if (src_folder)
4369                                 g_object_unref (src_folder);
4370
4371                 }
4372         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4373                 ModestEmailClipboard *clipboard = NULL;
4374                 TnyFolder *src_folder = NULL;
4375                 TnyFolderStore *folder_store = NULL;
4376                 TnyList *data = NULL;
4377                 gboolean delete = FALSE;
4378
4379                 /* Check clipboard source */
4380                 clipboard = modest_runtime_get_email_clipboard ();
4381                 if (modest_email_clipboard_cleared (clipboard))
4382                         return;
4383
4384                 /* Get elements to paste */
4385                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4386
4387                 /* Create a new mail operation */
4388                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4389
4390                 /* Get destination folder */
4391                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4392
4393                 /* transfer messages  */
4394                 if (data != NULL) {
4395                         gint response = 0;
4396
4397                         /* Ask for user confirmation */
4398                         response =
4399                                 modest_ui_actions_msgs_move_to_confirmation (window,
4400                                                                              TNY_FOLDER (folder_store),
4401                                                                              delete,
4402                                                                              data);
4403
4404                         if (response == GTK_RESPONSE_OK) {
4405                                 /* Launch notification */
4406                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4407                                                                              _CS("ckct_nw_pasting"));
4408                                 if (inf_note != NULL)  {
4409                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4410                                         gtk_widget_show (GTK_WIDGET(inf_note));
4411                                 }
4412
4413                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4414                                 modest_mail_operation_xfer_msgs (mail_op,
4415                                                                  data,
4416                                                                  TNY_FOLDER (folder_store),
4417                                                                  delete,
4418                                                                  destroy_information_note,
4419                                                                  inf_note);
4420                         } else {
4421                                 g_object_unref (mail_op);
4422                         }
4423
4424                 } else if (src_folder != NULL) {
4425                         /* Launch notification */
4426                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4427                                                                      _CS("ckct_nw_pasting"));
4428                         if (inf_note != NULL)  {
4429                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4430                                 gtk_widget_show (GTK_WIDGET(inf_note));
4431                         }
4432
4433                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4434                         modest_mail_operation_xfer_folder (mail_op,
4435                                                            src_folder,
4436                                                            folder_store,
4437                                                            delete,
4438                                                            destroy_folder_information_note,
4439                                                            inf_note);
4440                 }
4441
4442                 /* Free */
4443                 if (data != NULL)
4444                         g_object_unref (data);
4445                 if (src_folder != NULL)
4446                         g_object_unref (src_folder);
4447                 if (folder_store != NULL)
4448                         g_object_unref (folder_store);
4449         }
4450 }
4451
4452
4453 void
4454 modest_ui_actions_on_select_all (GtkAction *action,
4455                                  ModestWindow *window)
4456 {
4457         GtkWidget *focused_widget;
4458
4459         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4460         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4461                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4462         } else if (GTK_IS_LABEL (focused_widget)) {
4463                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4464         } else if (GTK_IS_EDITABLE (focused_widget)) {
4465                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4466         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4467                 GtkTextBuffer *buffer;
4468                 GtkTextIter start, end;
4469
4470                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4471                 gtk_text_buffer_get_start_iter (buffer, &start);
4472                 gtk_text_buffer_get_end_iter (buffer, &end);
4473                 gtk_text_buffer_select_range (buffer, &start, &end);
4474         } else if (GTK_IS_HTML (focused_widget)) {
4475                 gtk_html_select_all (GTK_HTML (focused_widget));
4476         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4477                 GtkWidget *header_view = focused_widget;
4478                 GtkTreeSelection *selection = NULL;
4479
4480                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4481                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4482                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4483                 }
4484
4485                 /* Disable window dimming management */
4486                 modest_window_disable_dimming (MODEST_WINDOW(window));
4487
4488                 /* Select all messages */
4489                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4490                 gtk_tree_selection_select_all (selection);
4491
4492                 /* Set focuse on header view */
4493                 gtk_widget_grab_focus (header_view);
4494
4495                 /* Enable window dimming management */
4496                 modest_window_enable_dimming (MODEST_WINDOW(window));
4497                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4498                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4499         }
4500
4501 }
4502
4503 void
4504 modest_ui_actions_on_mark_as_read (GtkAction *action,
4505                                    ModestWindow *window)
4506 {
4507         g_return_if_fail (MODEST_IS_WINDOW(window));
4508
4509         /* Mark each header as read */
4510         do_headers_action (window, headers_action_mark_as_read, NULL);
4511 }
4512
4513 void
4514 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4515                                      ModestWindow *window)
4516 {
4517         g_return_if_fail (MODEST_IS_WINDOW(window));
4518
4519         /* Mark each header as read */
4520         do_headers_action (window, headers_action_mark_as_unread, NULL);
4521 }
4522
4523 void
4524 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4525                                   GtkRadioAction *selected,
4526                                   ModestWindow *window)
4527 {
4528         gint value;
4529
4530         value = gtk_radio_action_get_current_value (selected);
4531         if (MODEST_IS_WINDOW (window)) {
4532                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4533         }
4534 }
4535
4536 void
4537 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4538                                                GtkRadioAction *selected,
4539                                                ModestWindow *window)
4540 {
4541         TnyHeaderFlags flags;
4542         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4543
4544         flags = gtk_radio_action_get_current_value (selected);
4545         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4546 }
4547
4548 void
4549 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4550                                                   GtkRadioAction *selected,
4551                                                   ModestWindow *window)
4552 {
4553         gint file_format;
4554
4555         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4556
4557         file_format = gtk_radio_action_get_current_value (selected);
4558         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4559 }
4560
4561
4562 void
4563 modest_ui_actions_on_zoom_plus (GtkAction *action,
4564                                 ModestWindow *window)
4565 {
4566         g_return_if_fail (MODEST_IS_WINDOW (window));
4567
4568         modest_window_zoom_plus (MODEST_WINDOW (window));
4569 }
4570
4571 void
4572 modest_ui_actions_on_zoom_minus (GtkAction *action,
4573                                  ModestWindow *window)
4574 {
4575         g_return_if_fail (MODEST_IS_WINDOW (window));
4576
4577         modest_window_zoom_minus (MODEST_WINDOW (window));
4578 }
4579
4580 void
4581 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4582                                            ModestWindow *window)
4583 {
4584         ModestWindowMgr *mgr;
4585         gboolean fullscreen, active;
4586         g_return_if_fail (MODEST_IS_WINDOW (window));
4587
4588         mgr = modest_runtime_get_window_mgr ();
4589
4590         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4591         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4592
4593         if (active != fullscreen) {
4594                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4595 #ifndef MODEST_TOOLKIT_HILDON2
4596                 gtk_window_present (GTK_WINDOW (window));
4597 #endif
4598         }
4599 }
4600
4601 void
4602 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4603                                         ModestWindow *window)
4604 {
4605         ModestWindowMgr *mgr;
4606         gboolean fullscreen;
4607
4608         g_return_if_fail (MODEST_IS_WINDOW (window));
4609
4610         mgr = modest_runtime_get_window_mgr ();
4611         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4612         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4613
4614 #ifndef MODEST_TOOLKIT_HILDON2
4615         gtk_window_present (GTK_WINDOW (window));
4616 #endif
4617 }
4618
4619 /*
4620  * Used by modest_ui_actions_on_details to call do_headers_action
4621  */
4622 static void
4623 headers_action_show_details (TnyHeader *header,
4624                              ModestWindow *window,
4625                              gpointer user_data)
4626
4627 {
4628         gboolean async_retrieval;
4629         TnyMsg *msg = NULL;
4630
4631         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4632                 async_retrieval = TRUE;
4633                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4634         } else {
4635                 async_retrieval = FALSE;
4636         }
4637         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4638         if (msg)
4639                 g_object_unref (msg);
4640 }
4641
4642 /*
4643  * Show the header details in a ModestDetailsDialog widget
4644  */
4645 void
4646 modest_ui_actions_on_details (GtkAction *action,
4647                               ModestWindow *win)
4648 {
4649         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4650                 TnyMsg *msg;
4651                 TnyHeader *header;
4652
4653                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4654                 if (!msg)
4655                         return;
4656
4657                 header = tny_msg_get_header (msg);
4658                 if (header) {
4659                         headers_action_show_details (header, win, NULL);
4660                         g_object_unref (header);
4661                 }
4662                 g_object_unref (msg);
4663
4664         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4665                 GtkWidget *folder_view, *header_view;
4666
4667                 /* Check which widget has the focus */
4668                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4669                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4670                 if (gtk_widget_is_focus (folder_view)) {
4671                         TnyFolderStore *folder_store
4672                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4673                         if (!folder_store) {
4674                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4675                                 return;
4676                         }
4677                         /* Show only when it's a folder */
4678                         /* This function should not be called for account items,
4679                          * because we dim the menu item for them. */
4680                         if (TNY_IS_FOLDER (folder_store)) {
4681                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4682                                                                            TNY_FOLDER (folder_store));
4683                         }
4684
4685                         g_object_unref (folder_store);
4686
4687                 } else {
4688                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4689                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4690                         /* Show details of each header */
4691                         do_headers_action (win, headers_action_show_details, header_view);
4692                 }
4693 #ifdef MODEST_TOOLKIT_HILDON2
4694         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4695                 TnyFolder *folder;
4696                 GtkWidget *header_view;
4697
4698                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4699                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4700                 if (folder) {
4701                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4702                                                                    folder);
4703                         g_object_unref (folder);
4704                 }
4705 #endif
4706         }
4707 }
4708
4709 void
4710 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4711                                      ModestMsgEditWindow *window)
4712 {
4713         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4714
4715         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4716 }
4717
4718 void
4719 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4720                                       ModestMsgEditWindow *window)
4721 {
4722         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4723
4724         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4725 }
4726
4727 void
4728 modest_ui_actions_toggle_folders_view (GtkAction *action,
4729                                        ModestMainWindow *main_window)
4730 {
4731         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4732
4733         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4734                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4735         else
4736                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4737 }
4738
4739 void
4740 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4741                                      ModestWindow *window)
4742 {
4743         gboolean active, fullscreen = FALSE;
4744         ModestWindowMgr *mgr;
4745
4746         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4747
4748         /* Check if we want to toggle the toolbar view in fullscreen
4749            or normal mode */
4750         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4751                      "ViewShowToolbarFullScreen")) {
4752                 fullscreen = TRUE;
4753         }
4754
4755         /* Toggle toolbar */
4756         mgr = modest_runtime_get_window_mgr ();
4757         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4758 }
4759
4760 void
4761 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4762                                            ModestMsgEditWindow *window)
4763 {
4764         modest_msg_edit_window_select_font (window);
4765 }
4766
4767
4768 void
4769 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4770                                                   const gchar *display_name,
4771                                                   GtkWindow *window)
4772 {
4773         /* don't update the display name if it was already set;
4774          * updating the display name apparently is expensive */
4775         const gchar* old_name = gtk_window_get_title (window);
4776
4777         if (display_name == NULL)
4778                 display_name = " ";
4779
4780         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4781                 return; /* don't do anything */
4782
4783         /* This is usually used to change the title of the main window, which
4784          * is the one that holds the folder view. Note that this change can
4785          * happen even when the widget doesn't have the focus. */
4786         gtk_window_set_title (window, display_name);
4787
4788 }
4789
4790 void
4791 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4792 {
4793         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4794         modest_msg_edit_window_select_contacts (window);
4795 }
4796
4797 void
4798 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4799 {
4800         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4801         modest_msg_edit_window_check_names (window, FALSE);
4802 }
4803
4804 #ifndef MODEST_TOOLKIT_HILDON2
4805 /*
4806  * This function is used to track changes in the selection of the
4807  * folder view that is inside the "move to" dialog to enable/disable
4808  * the OK button because we do not want the user to select a disallowed
4809  * destination for a folder.
4810  * The user also not desired to be able to use NEW button on items where
4811  * folder creation is not possibel.
4812  */
4813 static void
4814 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4815                                             TnyFolderStore *folder_store,
4816                                             gboolean selected,
4817                                             gpointer user_data)
4818 {
4819         GtkWidget *dialog = NULL;
4820         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4821         gboolean moving_folder = FALSE;
4822         gboolean is_local_account = TRUE;
4823         GtkWidget *folder_view = NULL;
4824         ModestTnyFolderRules rules;
4825
4826         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4827
4828         if (!selected)
4829                 return;
4830
4831         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4832         if (!dialog)
4833                 return;
4834
4835         /* check if folder_store is an remote account */
4836         if (TNY_IS_ACCOUNT (folder_store)) {
4837                 TnyAccount *local_account = NULL;
4838                 TnyAccount *mmc_account = NULL;
4839                 ModestTnyAccountStore *account_store = NULL;
4840
4841                 account_store = modest_runtime_get_account_store ();
4842                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4843                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4844
4845                 if ((gpointer) local_account != (gpointer) folder_store &&
4846                     (gpointer) mmc_account != (gpointer) folder_store) {
4847                         ModestProtocolType proto;
4848                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4849                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4850                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4851                         }
4852                         is_local_account = FALSE;
4853                         /* New button should be dimmed on remote
4854                            POP account root */
4855                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4856                                                                                          proto,
4857                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4858                 }
4859                 g_object_unref (local_account);
4860
4861                 /* It could not exist */
4862                 if (mmc_account)
4863                         g_object_unref (mmc_account);
4864         }
4865
4866         /* Check the target folder rules */
4867         if (TNY_IS_FOLDER (folder_store)) {
4868                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4869                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4870                         ok_sensitive = FALSE;
4871                         new_sensitive = FALSE;
4872                         goto end;
4873                 }
4874         }
4875
4876         /* Check if we're moving a folder */
4877         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4878                 /* Get the widgets */
4879                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4880                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4881                 if (gtk_widget_is_focus (folder_view))
4882                         moving_folder = TRUE;
4883         }
4884
4885         if (moving_folder) {
4886                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4887
4888                 /* Get the folder to move */
4889                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4890
4891                 /* Check that we're not moving to the same folder */
4892                 if (TNY_IS_FOLDER (moved_folder)) {
4893                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4894                         if (parent == folder_store)
4895                                 ok_sensitive = FALSE;
4896                         g_object_unref (parent);
4897                 }
4898
4899                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4900                         /* Do not allow to move to an account unless it's the
4901                            local folders account */
4902                         if (!is_local_account)
4903                                 ok_sensitive = FALSE;
4904                 }
4905
4906                 if (ok_sensitive && (moved_folder == folder_store)) {
4907                         /* Do not allow to move to itself */
4908                         ok_sensitive = FALSE;
4909                 }
4910                 g_object_unref (moved_folder);
4911         } else {
4912                 TnyFolder *src_folder = NULL;
4913
4914                 /* Moving a message */
4915                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4916
4917                         TnyHeader *header = NULL;
4918                         header = modest_msg_view_window_get_header
4919                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4920                         if (!TNY_IS_HEADER(header))
4921                                 g_warning ("%s: could not get source header", __FUNCTION__);
4922                         else
4923                                 src_folder = tny_header_get_folder (header);
4924
4925                         if (header)
4926                                 g_object_unref (header);
4927                 } else {
4928                         src_folder =
4929                                 TNY_FOLDER (modest_folder_view_get_selected
4930                                             (MODEST_FOLDER_VIEW (folder_view)));
4931                 }
4932
4933                 if (TNY_IS_FOLDER(src_folder)) {
4934                         /* Do not allow to move the msg to the same folder */
4935                         /* Do not allow to move the msg to an account */
4936                         if ((gpointer) src_folder == (gpointer) folder_store ||
4937                             TNY_IS_ACCOUNT (folder_store))
4938                                 ok_sensitive = FALSE;
4939                         g_object_unref (src_folder);
4940                 } else
4941                         g_warning ("%s: could not get source folder", __FUNCTION__);
4942         }
4943
4944  end:
4945         /* Set sensitivity of the OK and NEW button */
4946         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
4947         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
4948 }
4949 #endif
4950
4951 static void
4952 on_move_to_dialog_response (GtkDialog *dialog,
4953                             gint       response,
4954                             gpointer   user_data)
4955 {
4956         GtkWidget *parent_win;
4957         MoveToInfo *helper = NULL;
4958         ModestFolderView *folder_view;
4959
4960         helper = (MoveToInfo *) user_data;
4961
4962         parent_win = (GtkWidget *) helper->win;
4963         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4964                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4965
4966         switch (response) {
4967                 TnyFolderStore *dst_folder;
4968                 TnyFolderStore *selected;
4969
4970         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4971                 selected = modest_folder_view_get_selected (folder_view);
4972                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
4973                 g_object_unref (selected);
4974                 return;
4975         case GTK_RESPONSE_NONE:
4976         case GTK_RESPONSE_CANCEL:
4977         case GTK_RESPONSE_DELETE_EVENT:
4978                 break;
4979         case GTK_RESPONSE_OK:
4980                 dst_folder = modest_folder_view_get_selected (folder_view);
4981
4982                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
4983                         /* Clean list to move used for filtering */
4984                         modest_folder_view_set_list_to_move (folder_view, NULL);
4985
4986                         modest_ui_actions_on_main_window_move_to (NULL,
4987                                                                   GTK_WIDGET (folder_view),
4988                                                                   dst_folder,
4989                                                                   MODEST_MAIN_WINDOW (parent_win));
4990 #ifdef MODEST_TOOLKIT_HILDON2
4991                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4992                         /* Clean list to move used for filtering */
4993                         modest_folder_view_set_list_to_move (folder_view, NULL);
4994
4995                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4996                                                                     dst_folder,
4997                                                                     helper->list,
4998                                                                     GTK_WINDOW (parent_win));
4999 #endif
5000                 } else {
5001                         /* if the user selected a root folder
5002                            (account) then do not perform any action */
5003                         if (TNY_IS_ACCOUNT (dst_folder)) {
5004                                 g_signal_stop_emission_by_name (dialog, "response");
5005                                 return;
5006                         }
5007
5008                         /* Clean list to move used for filtering */
5009                         modest_folder_view_set_list_to_move (folder_view, NULL);
5010
5011                         /* Moving from headers window in edit mode */
5012                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5013                                                              dst_folder,
5014                                                              MODEST_WINDOW (parent_win));
5015                 }
5016
5017                 if (dst_folder)
5018                         g_object_unref (dst_folder);
5019
5020                 break;
5021         default:
5022                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5023         }
5024
5025         /* Free the helper and exit */
5026         if (helper->list)
5027                 g_object_unref (helper->list);
5028         g_slice_free (MoveToInfo, helper);
5029         gtk_widget_destroy (GTK_WIDGET (dialog));
5030 }
5031
5032 static GtkWidget*
5033 create_move_to_dialog (GtkWindow *win,
5034                        GtkWidget *folder_view,
5035                        TnyList *list_to_move)
5036 {
5037         GtkWidget *dialog, *tree_view = NULL;
5038
5039         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5040
5041 #ifndef MODEST_TOOLKIT_HILDON2
5042         /* Track changes in the selection to
5043          * disable the OK button whenever "Move to" is not possible
5044          * disbale NEW button whenever New is not possible */
5045         g_signal_connect (tree_view,
5046                           "folder_selection_changed",
5047                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5048                           win);
5049 #endif
5050
5051         /* It could happen that we're trying to move a message from a
5052            window (msg window for example) after the main window was
5053            closed, so we can not just get the model of the folder
5054            view */
5055         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5056                 const gchar *visible_id = NULL;
5057
5058                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5059                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5060                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5061                                                MODEST_FOLDER_VIEW(tree_view));
5062
5063                 visible_id =
5064                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5065
5066                 /* Show the same account than the one that is shown in the main window */
5067                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5068                                                                              visible_id);
5069         } else {
5070                 const gchar *active_account_name = NULL;
5071                 ModestAccountMgr *mgr = NULL;
5072                 ModestAccountSettings *settings = NULL;
5073                 ModestServerAccountSettings *store_settings = NULL;
5074
5075                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5076                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5077                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5078                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5079
5080                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5081                 mgr = modest_runtime_get_account_mgr ();
5082                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5083
5084                 if (settings) {
5085                         const gchar *store_account_name;
5086                         store_settings = modest_account_settings_get_store_settings (settings);
5087                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5088
5089                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5090                                                                                      store_account_name);
5091                         g_object_unref (store_settings);
5092                         g_object_unref (settings);
5093                 }
5094         }
5095
5096         /* we keep a pointer to the embedded folder view, so we can
5097          *   retrieve it with get_folder_view_from_move_to_dialog (see
5098          *   above) later (needed for focus handling)
5099          */
5100         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5101
5102         /* Hide special folders */
5103 #ifndef MODEST_TOOLKIT_HILDON2
5104         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5105 #endif
5106         if (list_to_move)
5107                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5108 #ifndef MODEST_TOOLKIT_HILDON2
5109         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5110 #endif
5111
5112         gtk_widget_show (GTK_WIDGET (tree_view));
5113
5114         return dialog;
5115 }
5116
5117 /*
5118  * Shows a confirmation dialog to the user when we're moving messages
5119  * from a remote server to the local storage. Returns the dialog
5120  * response. If it's other kind of movement then it always returns
5121  * GTK_RESPONSE_OK
5122  *
5123  * This one is used by the next functions:
5124  *      modest_ui_actions_on_paste                      - commented out
5125  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5126  */
5127 gint
5128 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5129                                              TnyFolder *dest_folder,
5130                                              gboolean delete,
5131                                              TnyList *headers)
5132 {
5133         gint response = GTK_RESPONSE_OK;
5134         TnyAccount *account = NULL;
5135         TnyFolder *src_folder = NULL;
5136         TnyIterator *iter = NULL;
5137         TnyHeader *header = NULL;
5138
5139         /* return with OK if the destination is a remote folder */
5140         if (modest_tny_folder_is_remote_folder (dest_folder))
5141                 return GTK_RESPONSE_OK;
5142
5143         /* Get source folder */
5144         iter = tny_list_create_iterator (headers);
5145         header = TNY_HEADER (tny_iterator_get_current (iter));
5146         if (header) {
5147                 src_folder = tny_header_get_folder (header);
5148                 g_object_unref (header);
5149         }
5150         g_object_unref (iter);
5151
5152         /* if no src_folder, message may be an attahcment */
5153         if (src_folder == NULL)
5154                 return GTK_RESPONSE_CANCEL;
5155
5156         /* If the source is a local or MMC folder */
5157         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5158                 g_object_unref (src_folder);
5159                 return GTK_RESPONSE_OK;
5160         }
5161
5162         /* Get the account */
5163         account = tny_folder_get_account (src_folder);
5164
5165         /* now if offline we ask the user */
5166         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5167                 response = GTK_RESPONSE_OK;
5168         else
5169                 response = GTK_RESPONSE_CANCEL;
5170
5171         /* Frees */
5172         g_object_unref (src_folder);
5173         g_object_unref (account);
5174
5175         return response;
5176 }
5177
5178 static void
5179 move_to_helper_destroyer (gpointer user_data)
5180 {
5181         MoveToHelper *helper = (MoveToHelper *) user_data;
5182
5183         /* Close the "Pasting" information banner */
5184         if (helper->banner) {
5185                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5186                 g_object_unref (helper->banner);
5187         }
5188         if (gtk_tree_row_reference_valid (helper->reference)) {
5189                 gtk_tree_row_reference_free (helper->reference);
5190                 helper->reference = NULL;
5191         }
5192         g_free (helper);
5193 }
5194
5195 static void
5196 move_to_cb (ModestMailOperation *mail_op,
5197             gpointer user_data)
5198 {
5199         MoveToHelper *helper = (MoveToHelper *) user_data;
5200         GObject *object = modest_mail_operation_get_source (mail_op);
5201
5202         /* Note that the operation could have failed, in that case do
5203            nothing */
5204         if (modest_mail_operation_get_status (mail_op) !=
5205             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5206                 goto frees;
5207
5208         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5209                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5210
5211                 if (!modest_msg_view_window_select_next_message (self) &&
5212                     !modest_msg_view_window_select_previous_message (self)) {
5213                         /* No more messages to view, so close this window */
5214                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5215                 }
5216         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5217                    gtk_tree_row_reference_valid (helper->reference)) {
5218                 GtkWidget *header_view;
5219                 GtkTreePath *path;
5220                 GtkTreeSelection *sel;
5221
5222                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5223                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5224                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5225                 path = gtk_tree_row_reference_get_path (helper->reference);
5226                 /* We need to unselect the previous one
5227                    because we could be copying instead of
5228                    moving */
5229                 gtk_tree_selection_unselect_all (sel);
5230                 gtk_tree_selection_select_path (sel, path);
5231                 gtk_tree_path_free (path);
5232         }
5233         g_object_unref (object);
5234
5235  frees:
5236         /* Destroy the helper */
5237         move_to_helper_destroyer (helper);
5238 }
5239
5240 static void
5241 folder_move_to_cb (ModestMailOperation *mail_op,
5242                    TnyFolder *new_folder,
5243                    gpointer user_data)
5244 {
5245         GtkWidget *folder_view;
5246         GObject *object;
5247
5248         object = modest_mail_operation_get_source (mail_op);
5249         if (MODEST_IS_MAIN_WINDOW (object)) {
5250                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5251                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5252                 g_object_ref (folder_view);
5253                 g_object_unref (object);
5254                 move_to_cb (mail_op, user_data);
5255                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5256                 g_object_unref (folder_view);
5257         } else {
5258                 move_to_cb (mail_op, user_data);
5259         }
5260 }
5261
5262 static void
5263 msgs_move_to_cb (ModestMailOperation *mail_op,
5264                  gpointer user_data)
5265 {
5266         move_to_cb (mail_op, user_data);
5267 }
5268
5269 void
5270 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5271                                              gpointer user_data)
5272 {
5273         GObject *win = NULL;
5274
5275 #ifndef MODEST_TOOLKIT_HILDON2
5276         ModestWindow *main_window = NULL;
5277
5278         /* Disable next automatic folder selection */
5279         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5280                                                          FALSE); /* don't create */
5281         if (main_window) {
5282                 GtkWidget *folder_view = NULL;
5283
5284                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5285                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5286                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5287
5288                 if (user_data && TNY_IS_FOLDER (user_data)) {
5289                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5290                                                           TNY_FOLDER (user_data), FALSE);
5291                 }
5292         }
5293 #endif
5294         /* Show notification dialog only if the main window exists */
5295         win = modest_mail_operation_get_source (mail_op);
5296         modest_platform_run_information_dialog ((GtkWindow *) win,
5297                                                 _("mail_in_ui_folder_move_target_error"),
5298                                                 FALSE);
5299         if (win)
5300                 g_object_unref (win);
5301 }
5302
5303 static void
5304 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5305                        TnyHeader *header,
5306                        gboolean canceled,
5307                        TnyMsg *msg,
5308                        GError *err,
5309                        gpointer user_data)
5310 {
5311         TnyList *parts;
5312         TnyIterator *iter;
5313         gint pending_purges = 0;
5314         gboolean some_purged = FALSE;
5315         ModestWindow *win = MODEST_WINDOW (user_data);
5316         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5317
5318         /* If there was any error */
5319         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5320                 modest_window_mgr_unregister_header (mgr, header);
5321                 return;
5322         }
5323
5324         /* Once the message has been retrieved for purging, we check if
5325          * it's all ok for purging */
5326
5327         parts = tny_simple_list_new ();
5328         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5329         iter = tny_list_create_iterator (parts);
5330
5331         while (!tny_iterator_is_done (iter)) {
5332                 TnyMimePart *part;
5333                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5334                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5335                         if (tny_mime_part_is_purged (part))
5336                                 some_purged = TRUE;
5337                         else
5338                                 pending_purges++;
5339                 }
5340
5341                 if (part)
5342                         g_object_unref (part);
5343
5344                 tny_iterator_next (iter);
5345         }
5346         g_object_unref (iter);
5347
5348
5349         if (pending_purges>0) {
5350                 gint response;
5351                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5352
5353                 if (response == GTK_RESPONSE_OK) {
5354                         GtkWidget *info;
5355                         info =
5356                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5357                         iter = tny_list_create_iterator (parts);
5358                         while (!tny_iterator_is_done (iter)) {
5359                                 TnyMimePart *part;
5360
5361                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5362                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5363                                         tny_mime_part_set_purged (part);
5364
5365                                 if (part)
5366                                         g_object_unref (part);
5367
5368                                 tny_iterator_next (iter);
5369                         }
5370                         g_object_unref (iter);
5371
5372                         tny_msg_rewrite_cache (msg);
5373
5374                         gtk_widget_destroy (info);
5375                 }
5376         }
5377
5378         modest_window_mgr_unregister_header (mgr, header);
5379
5380         g_object_unref (parts);
5381 }
5382
5383 static void
5384 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5385                                                      ModestMainWindow *win)
5386 {
5387         GtkWidget *header_view;
5388         TnyList *header_list;
5389         TnyHeader *header;
5390         TnyHeaderFlags flags;
5391         ModestWindow *msg_view_window =  NULL;
5392         gboolean found;
5393
5394         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5395
5396         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5397                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5398
5399         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5400         if (!header_list) {
5401                 g_warning ("%s: no header selected", __FUNCTION__);
5402                 return;
5403         }
5404
5405         if (tny_list_get_length (header_list) == 1) {
5406                 TnyIterator *iter = tny_list_create_iterator (header_list);
5407                 header = TNY_HEADER (tny_iterator_get_current (iter));
5408                 g_object_unref (iter);
5409         } else
5410                 return;
5411
5412         if (!header || !TNY_IS_HEADER(header)) {
5413                 g_warning ("%s: header is not valid", __FUNCTION__);
5414                 return;
5415         }
5416
5417         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5418                                                           header, &msg_view_window);
5419         flags = tny_header_get_flags (header);
5420         if (!(flags & TNY_HEADER_FLAG_CACHED))
5421                 return;
5422         if (found) {
5423                 if (msg_view_window != NULL)
5424                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5425                 else {
5426                         /* do nothing; uid was registered before, so window is probably on it's way */
5427                         g_warning ("debug: header %p has already been registered", header);
5428                 }
5429         } else {
5430                 ModestMailOperation *mail_op = NULL;
5431                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5432                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5433                                                                          modest_ui_actions_disk_operations_error_handler,
5434                                                                          NULL, NULL);
5435                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5436                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5437
5438                 g_object_unref (mail_op);
5439         }
5440         if (header)
5441                 g_object_unref (header);
5442         if (header_list)
5443                 g_object_unref (header_list);
5444 }
5445
5446 /*
5447  * Checks if we need a connection to do the transfer and if the user
5448  * wants to connect to complete it
5449  */
5450 static void
5451 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5452                                        TnyFolderStore *src_folder,
5453                                        TnyList *headers,
5454                                        TnyFolder *dst_folder,
5455                                        gboolean delete_originals,
5456                                        gboolean *need_connection,
5457                                        gboolean *do_xfer)
5458 {
5459         TnyAccount *src_account;
5460         gint uncached_msgs = 0;
5461
5462         /* We don't need any further check if
5463          *
5464          * 1- the source folder is local OR
5465          * 2- the device is already online
5466          */
5467         if (!modest_tny_folder_store_is_remote (src_folder) ||
5468             tny_device_is_online (modest_runtime_get_device())) {
5469                 *need_connection = FALSE;
5470                 *do_xfer = TRUE;
5471                 return;
5472         }
5473
5474         /* We must ask for a connection when
5475          *
5476          *   - the message(s) is not already cached   OR
5477          *   - the message(s) is cached but the leave_on_server setting
5478          * is FALSE (because we need to sync the source folder to
5479          * delete the message from the server (for IMAP we could do it
5480          * offline, it'll take place the next time we get a
5481          * connection)
5482          */
5483         uncached_msgs = header_list_count_uncached_msgs (headers);
5484         src_account = get_account_from_folder_store (src_folder);
5485         if (uncached_msgs > 0) {
5486                 guint num_headers;
5487                 const gchar *msg;
5488
5489                 *need_connection = TRUE;
5490                 num_headers = tny_list_get_length (headers);
5491                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5492
5493                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5494                     GTK_RESPONSE_CANCEL) {
5495                         *do_xfer = FALSE;
5496                 } else {
5497                         *do_xfer = TRUE;
5498                 }
5499         } else {
5500                 /* The transfer is possible and the user wants to */
5501                 *do_xfer = TRUE;
5502
5503                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5504                         const gchar *account_name;
5505                         gboolean leave_on_server;
5506
5507                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5508                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5509                                                                                   account_name);
5510
5511                         if (leave_on_server == TRUE) {
5512                                 *need_connection = FALSE;
5513                         } else {
5514                                 *need_connection = TRUE;
5515                         }
5516                 } else {
5517                         *need_connection = FALSE;
5518                 }
5519         }
5520
5521         /* Frees */
5522         g_object_unref (src_account);
5523 }
5524
5525 static void
5526 xfer_messages_error_handler (ModestMailOperation *mail_op,
5527                              gpointer user_data)
5528 {
5529         GObject *win;
5530         const GError *error;
5531
5532         win = modest_mail_operation_get_source (mail_op);
5533         error = modest_mail_operation_get_error (mail_op);
5534
5535         if (error && is_memory_full_error ((GError *) error, mail_op)) {
5536                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
5537                 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
5538                 g_free (msg);
5539         } else {
5540                 modest_platform_run_information_dialog ((GtkWindow *) win,
5541                                                         _("mail_in_ui_folder_move_target_error"),
5542                                                         FALSE);
5543         }
5544         if (win)
5545                 g_object_unref (win);
5546 }
5547
5548 typedef struct {
5549         TnyFolderStore *dst_folder;
5550         TnyList *headers;
5551 } XferMsgsHelper;
5552
5553 /**
5554  * Utility function that transfer messages from both the main window
5555  * and the msg view window when using the "Move to" dialog
5556  */
5557 static void
5558 xfer_messages_performer  (gboolean canceled,
5559                           GError *err,
5560                           GtkWindow *parent_window,
5561                           TnyAccount *account,
5562                           gpointer user_data)
5563 {
5564         ModestWindow *win = MODEST_WINDOW (parent_window);
5565         TnyAccount *dst_account = NULL;
5566         gboolean dst_forbids_message_add = FALSE;
5567         XferMsgsHelper *helper;
5568         MoveToHelper *movehelper;
5569         ModestMailOperation *mail_op;
5570
5571         helper = (XferMsgsHelper *) user_data;
5572
5573         if (canceled || err) {
5574                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5575                         /* Show the proper error message */
5576                         modest_ui_actions_on_account_connection_error (parent_window, account);
5577                 }
5578                 goto end;
5579         }
5580
5581         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5582
5583         /* tinymail will return NULL for local folders it seems */
5584         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5585                                                                                   modest_tny_account_get_protocol_type (dst_account),
5586                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5587         g_object_unref (dst_account);
5588
5589         if (dst_forbids_message_add) {
5590                 modest_platform_information_banner (GTK_WIDGET (win),
5591                                                     NULL,
5592                                                     ngettext("mail_in_ui_folder_move_target_error",
5593                                                              "mail_in_ui_folder_move_targets_error",
5594                                                              tny_list_get_length (helper->headers)));
5595                 goto end;
5596         }
5597
5598         movehelper = g_new0 (MoveToHelper, 1);
5599
5600 #ifndef MODEST_TOOLKIT_HILDON2
5601         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5602                                                                _CS("ckct_nw_pasting"));
5603         if (movehelper->banner != NULL)  {
5604                 g_object_ref (movehelper->banner);
5605                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5606         }
5607 #endif
5608
5609         if (MODEST_IS_MAIN_WINDOW (win)) {
5610                 GtkWidget *header_view =
5611                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5612                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5613                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5614         }
5615
5616         /* Perform the mail operation */
5617         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5618                                                                  xfer_messages_error_handler,
5619                                                                  movehelper, NULL);
5620         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5621                                          mail_op);
5622
5623         modest_mail_operation_xfer_msgs (mail_op,
5624                                          helper->headers,
5625                                          TNY_FOLDER (helper->dst_folder),
5626                                          TRUE,
5627                                          msgs_move_to_cb,
5628                                          movehelper);
5629
5630         g_object_unref (G_OBJECT (mail_op));
5631  end:
5632         g_object_unref (helper->dst_folder);
5633         g_object_unref (helper->headers);
5634         g_slice_free (XferMsgsHelper, helper);
5635 }
5636
5637 typedef struct {
5638         TnyFolder *src_folder;
5639         TnyFolderStore *dst_folder;
5640         gboolean delete_original;
5641         GtkWidget *folder_view;
5642 } MoveFolderInfo;
5643
5644 static void
5645 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5646                 TnyAccount *account, gpointer user_data)
5647 {
5648         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5649         GtkTreeSelection *sel;
5650         ModestMailOperation *mail_op = NULL;
5651
5652         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5653                 g_object_unref (G_OBJECT (info->src_folder));
5654                 g_object_unref (G_OBJECT (info->dst_folder));
5655                 g_free (info);
5656                 return;
5657         }
5658
5659         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5660 #ifndef MODEST_TOOLKIT_HILDON2
5661         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5662                         _CS("ckct_nw_pasting"));
5663         if (helper->banner != NULL)  {
5664                 g_object_ref (helper->banner);
5665                 gtk_widget_show (GTK_WIDGET(helper->banner));
5666         }
5667 #endif
5668         /* Clean folder on header view before moving it */
5669         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5670         gtk_tree_selection_unselect_all (sel);
5671
5672         /* Let gtk events run. We need that the folder
5673            view frees its reference to the source
5674            folder *before* issuing the mail operation
5675            so we need the signal handler of selection
5676            changed to happen before the mail
5677            operation
5678         while (gtk_events_pending ())
5679                 gtk_main_iteration ();   */
5680
5681         mail_op =
5682                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5683                                 modest_ui_actions_move_folder_error_handler,
5684                                 info->src_folder, NULL);
5685         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5686                         mail_op);
5687
5688         /* Select *after* the changes */
5689         /* TODO: this function hangs UI after transfer */
5690         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5691         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5692
5693         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5694                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5695                                                   TNY_FOLDER (info->dst_folder), TRUE);
5696         }
5697         modest_mail_operation_xfer_folder (mail_op,
5698                         TNY_FOLDER (info->src_folder),
5699                         info->dst_folder,
5700                         info->delete_original,
5701                         folder_move_to_cb,
5702                         helper);
5703         g_object_unref (G_OBJECT (info->src_folder));
5704
5705         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5706         /* } */
5707
5708         /* Unref mail operation */
5709         g_object_unref (G_OBJECT (mail_op));
5710         g_object_unref (G_OBJECT (info->dst_folder));
5711         g_free (user_data);
5712 }
5713
5714 static TnyAccount *
5715 get_account_from_folder_store (TnyFolderStore *folder_store)
5716 {
5717         if (TNY_IS_ACCOUNT (folder_store))
5718                 return g_object_ref (folder_store);
5719         else
5720                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5721 }
5722
5723 /*
5724  * UI handler for the "Move to" action when invoked from the
5725  * ModestMainWindow
5726  */
5727 static void
5728 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5729                                           GtkWidget *folder_view,
5730                                           TnyFolderStore *dst_folder,
5731                                           ModestMainWindow *win)
5732 {
5733         ModestHeaderView *header_view = NULL;
5734         TnyFolderStore *src_folder = NULL;
5735
5736         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5737
5738         /* Get the source folder */
5739         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5740
5741         /* Get header view */
5742         header_view = (ModestHeaderView *)
5743                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5744
5745         /* Get folder or messages to transfer */
5746         if (gtk_widget_is_focus (folder_view)) {
5747                 gboolean do_xfer = TRUE;
5748
5749                 /* Allow only to transfer folders to the local root folder */
5750                 if (TNY_IS_ACCOUNT (dst_folder) &&
5751                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5752                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5753                         do_xfer = FALSE;
5754                 } else if (!TNY_IS_FOLDER (src_folder)) {
5755                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5756                         do_xfer = FALSE;
5757                 }
5758
5759                 if (do_xfer) {
5760                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5761                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5762
5763                         info->src_folder = g_object_ref (src_folder);
5764                         info->dst_folder = g_object_ref (dst_folder);
5765                         info->delete_original = TRUE;
5766                         info->folder_view = folder_view;
5767
5768                         connect_info->callback = on_move_folder_cb;
5769                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5770                         connect_info->data = info;
5771
5772                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5773                                                                    TNY_FOLDER_STORE (src_folder),
5774                                                                    connect_info);
5775                 }
5776         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5777                 TnyList *headers;
5778
5779                 headers = modest_header_view_get_selected_headers(header_view);
5780
5781                 /* Transfer the messages */
5782                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5783                                                             headers, TNY_FOLDER (dst_folder));
5784
5785                 g_object_unref (headers);
5786         }
5787
5788         /* Frees */
5789         g_object_unref (src_folder);
5790 }
5791
5792 #ifdef MODEST_TOOLKIT_HILDON2
5793 /*
5794  * UI handler for the "Move to" action when invoked from the
5795  * ModestFolderWindow
5796  */
5797 static void
5798 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5799                                             TnyFolderStore *dst_folder,
5800                                             TnyList *selection,
5801                                             GtkWindow *win)
5802 {
5803         TnyFolderStore *src_folder = NULL;
5804         TnyIterator *iterator;
5805
5806         if (tny_list_get_length (selection) != 1)
5807                 return;
5808
5809         iterator = tny_list_create_iterator (selection);
5810         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5811         g_object_unref (iterator);
5812
5813
5814         gboolean do_xfer = TRUE;
5815
5816         /* Allow only to transfer folders to the local root folder */
5817         if (TNY_IS_ACCOUNT (dst_folder) &&
5818             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5819             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5820                 do_xfer = FALSE;
5821                 /* Show an error */
5822                 modest_platform_run_information_dialog (win,
5823                                                         _("mail_in_ui_folder_move_target_error"),
5824                                                         FALSE);
5825         } else if (!TNY_IS_FOLDER (src_folder)) {
5826                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5827                 do_xfer = FALSE;
5828         }
5829
5830         if (do_xfer) {
5831                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5832                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5833
5834                 info->src_folder = g_object_ref (src_folder);
5835                 info->dst_folder = g_object_ref (dst_folder);
5836                 info->delete_original = TRUE;
5837                 info->folder_view = folder_view;
5838
5839                 connect_info->callback = on_move_folder_cb;
5840                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5841                 connect_info->data = info;
5842
5843                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5844                                                            TNY_FOLDER_STORE (src_folder),
5845                                                            connect_info);
5846         }
5847
5848         /* Frees */
5849         g_object_unref (src_folder);
5850 }
5851 #endif
5852
5853
5854 void
5855 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5856                                             TnyFolder *src_folder,
5857                                             TnyList *headers,
5858                                             TnyFolder *dst_folder)
5859 {
5860         gboolean need_connection = TRUE;
5861         gboolean do_xfer = TRUE;
5862         XferMsgsHelper *helper;
5863
5864         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5865         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5866         g_return_if_fail (TNY_IS_LIST (headers));
5867
5868         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5869                                                headers, TNY_FOLDER (dst_folder),
5870                                                TRUE, &need_connection,
5871                                                &do_xfer);
5872
5873         /* If we don't want to transfer just return */
5874         if (!do_xfer)
5875                 return;
5876
5877         /* Create the helper */
5878         helper = g_slice_new (XferMsgsHelper);
5879         helper->dst_folder = g_object_ref (dst_folder);
5880         helper->headers = g_object_ref (headers);
5881
5882         if (need_connection) {
5883                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5884                 connect_info->callback = xfer_messages_performer;
5885                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5886                 connect_info->data = helper;
5887
5888                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5889                                                            TNY_FOLDER_STORE (src_folder),
5890                                                            connect_info);
5891         } else {
5892                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5893                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5894                                          src_account, helper);
5895                 g_object_unref (src_account);
5896         }
5897 }
5898
5899 /*
5900  * UI handler for the "Move to" action when invoked from the
5901  * ModestMsgViewWindow
5902  */
5903 static void
5904 modest_ui_actions_on_window_move_to (GtkAction *action,
5905                                      TnyList *headers,
5906                                      TnyFolderStore *dst_folder,
5907                                      ModestWindow *win)
5908 {
5909         TnyFolder *src_folder = NULL;
5910
5911         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5912
5913         if (headers) {
5914                 TnyHeader *header = NULL;
5915                 TnyIterator *iter;
5916
5917                 iter = tny_list_create_iterator (headers);
5918                 header = (TnyHeader *) tny_iterator_get_current (iter);
5919                 src_folder = tny_header_get_folder (header);
5920
5921                 /* Transfer the messages */
5922                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
5923                                                             headers,
5924                                                             TNY_FOLDER (dst_folder));
5925
5926                 /* Frees */
5927                 g_object_unref (header);
5928                 g_object_unref (iter);
5929                 g_object_unref (src_folder);
5930         }
5931 }
5932
5933 void
5934 modest_ui_actions_on_move_to (GtkAction *action,
5935                               ModestWindow *win)
5936 {
5937         modest_ui_actions_on_edit_mode_move_to (win);
5938 }
5939
5940 gboolean
5941 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5942 {
5943         GtkWidget *dialog = NULL;
5944         MoveToInfo *helper = NULL;
5945         TnyList *list_to_move;
5946
5947         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5948
5949 #ifndef MODEST_TOOLKIT_HILDON2
5950         /* Get the main window if exists */
5951         ModestMainWindow *main_window;
5952         if (MODEST_IS_MAIN_WINDOW (win))
5953                 main_window = MODEST_MAIN_WINDOW (win);
5954         else
5955                 main_window =
5956                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5957                                                                                FALSE)); /* don't create */
5958 #endif
5959
5960         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5961
5962         if (!list_to_move)
5963                 return FALSE;
5964
5965         if (tny_list_get_length (list_to_move) < 1) {
5966                 g_object_unref (list_to_move);
5967                 return FALSE;
5968         }
5969
5970         /* Create and run the dialog */
5971         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
5972         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5973                                      GTK_WINDOW (dialog),
5974                                      (GtkWindow *) win);
5975
5976         /* Create helper */
5977         helper = g_slice_new0 (MoveToInfo);
5978         helper->list = list_to_move;
5979         helper->win = win;
5980
5981         /* Listen to response signal */
5982         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5983
5984         /* Show the dialog */
5985         gtk_widget_show (dialog);
5986
5987         return TRUE;
5988 }
5989
5990 /*
5991  * Calls #HeadersFunc for each header already selected in the main
5992  * window or the message currently being shown in the msg view window
5993  */
5994 static void
5995 do_headers_action (ModestWindow *win,
5996                    HeadersFunc func,
5997                    gpointer user_data)
5998 {
5999         TnyList *headers_list = NULL;
6000         TnyIterator *iter = NULL;
6001         TnyHeader *header = NULL;
6002         TnyFolder *folder = NULL;
6003
6004         /* Get headers */
6005         headers_list = get_selected_headers (win);
6006         if (!headers_list)
6007                 return;
6008
6009         /* Get the folder */
6010         iter = tny_list_create_iterator (headers_list);
6011         header = TNY_HEADER (tny_iterator_get_current (iter));
6012         if (header) {
6013                 folder = tny_header_get_folder (header);
6014                 g_object_unref (header);
6015         }
6016
6017         /* Call the function for each header */
6018         while (!tny_iterator_is_done (iter)) {
6019                 header = TNY_HEADER (tny_iterator_get_current (iter));
6020                 func (header, win, user_data);
6021                 g_object_unref (header);
6022                 tny_iterator_next (iter);
6023         }
6024
6025         /* Trick: do a poke status in order to speed up the signaling
6026            of observers */
6027         if (folder) {
6028                 tny_folder_poke_status (folder);
6029                 g_object_unref (folder);
6030         }
6031
6032         /* Frees */
6033         g_object_unref (iter);
6034         g_object_unref (headers_list);
6035 }
6036
6037 void
6038 modest_ui_actions_view_attachment (GtkAction *action,
6039                                    ModestWindow *window)
6040 {
6041         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6042                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6043         } else {
6044                 /* not supported window for this action */
6045                 g_return_if_reached ();
6046         }
6047 }
6048
6049 void
6050 modest_ui_actions_save_attachments (GtkAction *action,
6051                                     ModestWindow *window)
6052 {
6053         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6054
6055                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6056                         return;
6057
6058                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6059         } else {
6060                 /* not supported window for this action */
6061                 g_return_if_reached ();
6062         }
6063 }
6064
6065 void
6066 modest_ui_actions_remove_attachments (GtkAction *action,
6067                                       ModestWindow *window)
6068 {
6069         if (MODEST_IS_MAIN_WINDOW (window)) {
6070                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6071         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6072                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6073         } else {
6074                 /* not supported window for this action */
6075                 g_return_if_reached ();
6076         }
6077 }
6078
6079 void
6080 modest_ui_actions_on_settings (GtkAction *action,
6081                                ModestWindow *win)
6082 {
6083         GtkWidget *dialog;
6084
6085         dialog = modest_platform_get_global_settings_dialog ();
6086         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6087         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6088         gtk_widget_show_all (dialog);
6089
6090         gtk_dialog_run (GTK_DIALOG (dialog));
6091
6092         gtk_widget_destroy (dialog);
6093 }
6094
6095 void
6096 modest_ui_actions_on_help (GtkAction *action,
6097                            GtkWindow *win)
6098 {
6099         /* Help app is not available at all in fremantle */
6100 #ifndef MODEST_TOOLKIT_HILDON2
6101         const gchar *help_id;
6102
6103         g_return_if_fail (win && GTK_IS_WINDOW(win));
6104
6105         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6106
6107         if (help_id)
6108                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6109 #endif
6110 }
6111
6112 void
6113 modest_ui_actions_on_csm_help (GtkAction *action,
6114                                GtkWindow *win)
6115 {
6116         /* Help app is not available at all in fremantle */
6117 #ifndef MODEST_TOOLKIT_HILDON2
6118
6119         const gchar* help_id = NULL;
6120         GtkWidget *folder_view;
6121         TnyFolderStore *folder_store;
6122
6123         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6124
6125         /* Get selected folder */
6126         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6127                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6128         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6129
6130         /* Switch help_id */
6131         if (folder_store && TNY_IS_FOLDER (folder_store))
6132                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6133
6134         if (folder_store)
6135                 g_object_unref (folder_store);
6136
6137         if (help_id)
6138                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6139         else
6140                 modest_ui_actions_on_help (action, win);
6141 #endif
6142 }
6143
6144 static void
6145 retrieve_contents_cb (ModestMailOperation *mail_op,
6146                       TnyHeader *header,
6147                       gboolean canceled,
6148                       TnyMsg *msg,
6149                       GError *err,
6150                       gpointer user_data)
6151 {
6152         /* We only need this callback to show an error in case of
6153            memory low condition */
6154         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6155                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6156         }
6157 }
6158
6159 static void
6160 retrieve_msg_contents_performer (gboolean canceled,
6161                                  GError *err,
6162                                  GtkWindow *parent_window,
6163                                  TnyAccount *account,
6164                                  gpointer user_data)
6165 {
6166         ModestMailOperation *mail_op;
6167         TnyList *headers = TNY_LIST (user_data);
6168
6169         if (err || canceled) {
6170                 check_memory_full_error ((GtkWidget *) parent_window, err);
6171                 goto out;
6172         }
6173
6174         /* Create mail operation */
6175         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6176                                                                  modest_ui_actions_disk_operations_error_handler,
6177                                                                  NULL, NULL);
6178         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6179         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6180
6181         /* Frees */
6182         g_object_unref (mail_op);
6183  out:
6184         g_object_unref (headers);
6185         g_object_unref (account);
6186 }
6187
6188 void
6189 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6190                                             ModestWindow *window)
6191 {
6192         TnyList *headers = NULL;
6193         TnyAccount *account = NULL;
6194         TnyIterator *iter = NULL;
6195         TnyHeader *header = NULL;
6196         TnyFolder *folder = NULL;
6197
6198         /* Get headers */
6199         headers = get_selected_headers (window);
6200         if (!headers)
6201                 return;
6202
6203         /* Pick the account */
6204         iter = tny_list_create_iterator (headers);
6205         header = TNY_HEADER (tny_iterator_get_current (iter));
6206         folder = tny_header_get_folder (header);
6207         account = tny_folder_get_account (folder);
6208         g_object_unref (folder);
6209         g_object_unref (header);
6210         g_object_unref (iter);
6211
6212         /* Connect and perform the message retrieval */
6213         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6214                                              g_object_ref (account),
6215                                              retrieve_msg_contents_performer,
6216                                              g_object_ref (headers));
6217
6218         /* Frees */
6219         g_object_unref (account);
6220         g_object_unref (headers);
6221 }
6222
6223 void
6224 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6225 {
6226         g_return_if_fail (MODEST_IS_WINDOW (window));
6227
6228         /* Update dimmed */
6229         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6230 }
6231
6232 void
6233 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6234 {
6235         g_return_if_fail (MODEST_IS_WINDOW (window));
6236
6237         /* Update dimmed */
6238         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6239 }
6240
6241 void
6242 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6243                                           ModestWindow *window)
6244 {
6245         g_return_if_fail (MODEST_IS_WINDOW (window));
6246
6247         /* Update dimmed */
6248         modest_ui_actions_check_menu_dimming_rules (window);
6249 }
6250
6251 void
6252 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6253                                           ModestWindow *window)
6254 {
6255         g_return_if_fail (MODEST_IS_WINDOW (window));
6256
6257         /* Update dimmed */
6258         modest_ui_actions_check_menu_dimming_rules (window);
6259 }
6260
6261 void
6262 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6263                                           ModestWindow *window)
6264 {
6265         g_return_if_fail (MODEST_IS_WINDOW (window));
6266
6267         /* Update dimmed */
6268         modest_ui_actions_check_menu_dimming_rules (window);
6269 }
6270
6271 void
6272 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6273                                             ModestWindow *window)
6274 {
6275         g_return_if_fail (MODEST_IS_WINDOW (window));
6276
6277         /* Update dimmed */
6278         modest_ui_actions_check_menu_dimming_rules (window);
6279 }
6280
6281 void
6282 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6283                                           ModestWindow *window)
6284 {
6285         g_return_if_fail (MODEST_IS_WINDOW (window));
6286
6287         /* Update dimmed */
6288         modest_ui_actions_check_menu_dimming_rules (window);
6289 }
6290
6291 void
6292 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6293                                           ModestWindow *window)
6294 {
6295         g_return_if_fail (MODEST_IS_WINDOW (window));
6296
6297         /* Update dimmed */
6298         modest_ui_actions_check_menu_dimming_rules (window);
6299 }
6300
6301 void
6302 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6303                                                  ModestWindow *window)
6304 {
6305         g_return_if_fail (MODEST_IS_WINDOW (window));
6306
6307         /* Update dimmed */
6308         modest_ui_actions_check_menu_dimming_rules (window);
6309 }
6310
6311 void
6312 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6313                                                      ModestWindow *window)
6314 {
6315         g_return_if_fail (MODEST_IS_WINDOW (window));
6316
6317         /* Update dimmed */
6318         modest_ui_actions_check_menu_dimming_rules (window);
6319 }
6320
6321 void
6322 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6323                                                      ModestWindow *window)
6324 {
6325         g_return_if_fail (MODEST_IS_WINDOW (window));
6326
6327         /* Update dimmed */
6328         modest_ui_actions_check_menu_dimming_rules (window);
6329 }
6330
6331 void
6332 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6333 {
6334         g_return_if_fail (MODEST_IS_WINDOW (window));
6335
6336         /* we check for low-mem; in that case, show a warning, and don't allow
6337          * searching
6338          */
6339         if (modest_platform_check_memory_low (window, TRUE))
6340                 return;
6341
6342         modest_platform_show_search_messages (GTK_WINDOW (window));
6343 }
6344
6345 void
6346 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6347 {
6348         g_return_if_fail (MODEST_IS_WINDOW (win));
6349
6350
6351         /* we check for low-mem; in that case, show a warning, and don't allow
6352          * for the addressbook
6353          */
6354         if (modest_platform_check_memory_low (win, TRUE))
6355                 return;
6356
6357
6358         modest_platform_show_addressbook (GTK_WINDOW (win));
6359 }
6360
6361
6362 void
6363 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6364                                           ModestWindow *window)
6365 {
6366         gboolean active;
6367         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6368
6369         if (GTK_IS_TOGGLE_ACTION (action))
6370                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6371         else
6372                 active = TRUE;
6373
6374         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6375                                                     active);
6376 }
6377
6378 static void
6379 on_send_receive_finished (ModestMailOperation  *mail_op,
6380                            gpointer user_data)
6381 {
6382         GtkWidget *header_view, *folder_view;
6383         TnyFolderStore *folder_store;
6384         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6385
6386         /* Set send/receive operation finished */
6387         modest_main_window_notify_send_receive_completed (main_win);
6388
6389         /* Don't refresh the current folder if there were any errors */
6390         if (modest_mail_operation_get_status (mail_op) !=
6391             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6392                 return;
6393
6394         /* Refresh the current folder if we're viewing a window. We do
6395            this because the user won't be able to see the new mails in
6396            the selected folder after a Send&Receive because it only
6397            performs a poke_status, i.e, only the number of read/unread
6398            messages is updated, but the new headers are not
6399            downloaded */
6400         folder_view = modest_main_window_get_child_widget (main_win,
6401                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6402         if (!folder_view)
6403                 return;
6404
6405         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6406
6407         /* Do not need to refresh INBOX again because the
6408            update_account does it always automatically */
6409         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6410             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6411                 ModestMailOperation *refresh_op;
6412
6413                 header_view = modest_main_window_get_child_widget (main_win,
6414                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6415
6416                 /* We do not need to set the contents style
6417                    because it hasn't changed. We also do not
6418                    need to save the widget status. Just force
6419                    a refresh */
6420                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6421                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6422                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6423                                                       folder_refreshed_cb, main_win);
6424                 g_object_unref (refresh_op);
6425         }
6426
6427         if (folder_store)
6428                 g_object_unref (folder_store);
6429 }
6430
6431
6432 void
6433 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6434                                                 TnyHeader *header,
6435                                                 TnyMsg *msg,
6436                                                 GError *err,
6437                                                 gpointer user_data)
6438 {
6439         const gchar* server_name = NULL;
6440         TnyTransportAccount *transport;
6441         gchar *message = NULL;
6442         ModestProtocol *protocol;
6443
6444         /* Don't show anything if the user cancelled something or the
6445          * send receive request is not interactive. Authentication
6446          * errors are managed by the account store so no need to show
6447          * a dialog here again */
6448         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6449             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6450             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6451                 return;
6452
6453
6454         /* Get the server name. Note that we could be using a
6455            connection specific transport account */
6456         transport = (TnyTransportAccount *)
6457                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6458         if (transport) {
6459                 ModestTnyAccountStore *acc_store;
6460                 const gchar *acc_name;
6461                 TnyTransportAccount *conn_specific;
6462
6463                 acc_store = modest_runtime_get_account_store();
6464                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6465                 conn_specific = (TnyTransportAccount *)
6466                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6467                 if (conn_specific) {
6468                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6469                         g_object_unref (conn_specific);
6470                 } else {
6471                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6472                 }
6473                 g_object_unref (transport);
6474         }
6475
6476         /* Get protocol */
6477         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6478                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6479                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6480         if (!protocol) {
6481                 g_warning ("%s: Account with no proto", __FUNCTION__);
6482                 return;
6483         }
6484
6485         /* Show the appropriate message text for the GError: */
6486         switch (err->code) {
6487         case TNY_SERVICE_ERROR_CONNECT:
6488                 message = modest_protocol_get_translation (protocol,
6489                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6490                                                            server_name);
6491                 break;
6492         case TNY_SERVICE_ERROR_SEND:
6493                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6494                 break;
6495         case TNY_SERVICE_ERROR_UNAVAILABLE:
6496                 message = modest_protocol_get_translation (protocol,
6497                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6498                                                            server_name);
6499                 break;
6500         default:
6501                 g_warning ("%s: unexpected ERROR %d",
6502                            __FUNCTION__, err->code);
6503                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6504                 break;
6505         }
6506
6507         modest_platform_run_information_dialog (NULL, message, FALSE);
6508         g_free (message);
6509 }
6510
6511 void
6512 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6513                                                 gchar *msg_id,
6514                                                 guint status,
6515                                                 gpointer user_data)
6516 {
6517         ModestWindow *top_window = NULL;
6518         ModestWindowMgr *mgr = NULL;
6519         GtkWidget *header_view = NULL;
6520         TnyFolder *selected_folder = NULL;
6521         TnyFolderType folder_type;
6522
6523         mgr = modest_runtime_get_window_mgr ();
6524         top_window = modest_window_mgr_get_current_top (mgr);
6525
6526         if (!top_window)
6527                 return;
6528
6529 #ifndef MODEST_TOOLKIT_HILDON2
6530         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6531                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6532                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6533         }
6534 #else
6535         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6536                 header_view = (GtkWidget *)
6537                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6538         }
6539 #endif
6540
6541         /* Get selected folder */
6542         if (header_view)
6543                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6544         if (!selected_folder)
6545                 return;
6546
6547         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6548 #if GTK_CHECK_VERSION(2, 8, 0)
6549         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6550         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6551                 GtkTreeViewColumn *tree_column;
6552
6553                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6554                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6555                 if (tree_column)
6556                         gtk_tree_view_column_queue_resize (tree_column);
6557                 }
6558 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6559         gtk_widget_queue_draw (header_view);
6560 #endif
6561
6562 #ifndef MODEST_TOOLKIT_HILDON2
6563         /* Rerun dimming rules, because the message could become deletable for example */
6564         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6565                                                  MODEST_DIMMING_RULES_TOOLBAR);
6566         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6567                                                  MODEST_DIMMING_RULES_MENU);
6568 #endif
6569
6570         /* Free */
6571         g_object_unref (selected_folder);
6572 }
6573
6574 void
6575 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6576                                                TnyAccount *account)
6577 {
6578         ModestProtocolType protocol_type;
6579         ModestProtocol *protocol;
6580         gchar *error_note = NULL;
6581
6582         protocol_type = modest_tny_account_get_protocol_type (account);
6583         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6584                                                                   protocol_type);
6585
6586         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6587         if (error_note == NULL) {
6588                 g_warning ("%s: This should not be reached", __FUNCTION__);
6589         } else {
6590                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6591                 g_free (error_note);
6592         }
6593 }
6594
6595 gchar *
6596 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6597 {
6598         gchar *msg = NULL;
6599         gchar *subject;
6600         TnyFolderStore *folder = NULL;
6601         TnyAccount *account = NULL;
6602         ModestProtocolType proto;
6603         ModestProtocol *protocol;
6604         TnyHeader *header = NULL;
6605
6606         if (MODEST_IS_MAIN_WINDOW (win)) {
6607                 GtkWidget *header_view;
6608                 TnyList* headers = NULL;
6609                 TnyIterator *iter;
6610                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6611                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6612                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6613                 if (!headers || tny_list_get_length (headers) == 0) {
6614                         if (headers)
6615                                 g_object_unref (headers);
6616                         return NULL;
6617                 }
6618                 iter = tny_list_create_iterator (headers);
6619                 header = TNY_HEADER (tny_iterator_get_current (iter));
6620                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6621                 g_object_unref (iter);
6622                 g_object_unref (headers);
6623 #ifdef MODEST_TOOLKIT_HILDON2
6624         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6625                 GtkWidget *header_view;
6626                 TnyList* headers = NULL;
6627                 TnyIterator *iter;
6628                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6629                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6630                 if (!headers || tny_list_get_length (headers) == 0) {
6631                         if (headers)
6632                                 g_object_unref (headers);
6633                         return NULL;
6634                 }
6635                 iter = tny_list_create_iterator (headers);
6636                 header = TNY_HEADER (tny_iterator_get_current (iter));
6637                 if (header) {
6638                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6639                 } else {
6640                         g_warning ("List should contain headers");
6641                 }
6642                 g_object_unref (iter);
6643                 g_object_unref (headers);
6644 #endif
6645         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6646                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6647                 if (header)
6648                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6649         }
6650
6651         if (!header || !folder)
6652                 goto frees;
6653
6654         /* Get the account type */
6655         account = tny_folder_get_account (TNY_FOLDER (folder));
6656         proto = modest_tny_account_get_protocol_type (account);
6657         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6658                                                                   proto);
6659
6660         subject = tny_header_dup_subject (header);
6661         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6662         if (subject)
6663                 g_free (subject);
6664         if (msg == NULL) {
6665                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6666         }
6667
6668  frees:
6669         /* Frees */
6670         if (account)
6671                 g_object_unref (account);
6672         if (folder)
6673                 g_object_unref (folder);
6674         if (header)
6675                 g_object_unref (header);
6676
6677         return msg;
6678 }
6679
6680 gboolean
6681 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6682                                      const gchar *account_name,
6683                                      const gchar *account_title)
6684 {
6685         ModestAccountMgr *account_mgr;
6686         gchar *txt = NULL;
6687         gint response;
6688         ModestProtocol *protocol;
6689         gboolean removed = FALSE;
6690
6691         g_return_val_if_fail (account_name, FALSE);
6692         g_return_val_if_fail (account_title, FALSE);
6693
6694         account_mgr = modest_runtime_get_account_mgr();
6695
6696         /* The warning text depends on the account type: */
6697         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6698                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6699                                                                                                          account_name));
6700         txt = modest_protocol_get_translation (protocol,
6701                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6702                                                account_title);
6703         if (txt == NULL)
6704                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6705
6706         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6707         g_free (txt);
6708         txt = NULL;
6709
6710         if (response == GTK_RESPONSE_OK) {
6711                 /* Remove account. If it succeeds then it also removes
6712                    the account from the ModestAccountView: */
6713                 gboolean is_default = FALSE;
6714                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6715                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6716                         is_default = TRUE;
6717                 g_free (default_account_name);
6718
6719                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6720                 if (!removed)
6721                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6722         }
6723         return removed;
6724 }
6725
6726 void 
6727 modest_ui_actions_on_fetch_images (GtkAction *action,
6728                                    ModestWindow *window)
6729 {
6730         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6731
6732         modest_msg_view_window_fetch_images (MODEST_MSG_VIEW_WINDOW (window));
6733
6734 }
6735
6736 void
6737 modest_ui_actions_on_reload_message (const gchar *msg_id)
6738 {
6739         ModestWindow *window = NULL;
6740
6741         g_return_if_fail (msg_id && msg_id[0] != '\0');
6742         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6743                                                             msg_id,
6744                                                             &window))
6745                 return;
6746
6747
6748         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6749                 return;
6750
6751         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6752 }