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