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