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