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