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