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