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