8986d61aa431d8828f5b623e2460e089e35ecc3d
[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 *header_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         header_view = 
2369                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2370
2371         if (header_view) {
2372                 TnyFolder *current_folder;
2373
2374                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2375                 if (current_folder != NULL && folder != current_folder) {
2376                         g_object_unref (current_folder);
2377                         return;
2378                 } else if (current_folder)
2379                         g_object_unref (current_folder);
2380         }
2381
2382         /* Check if folder is empty and set headers view contents style */
2383         if (tny_folder_get_all_count (folder) == 0)
2384                 modest_main_window_set_contents_style (win,
2385                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2386
2387 }
2388
2389 void 
2390 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2391                                                TnyFolderStore *folder_store, 
2392                                                gboolean selected,
2393                                                ModestMainWindow *main_window)
2394 {
2395         ModestConf *conf;
2396         GtkWidget *header_view;
2397
2398         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2399
2400         header_view = modest_main_window_get_child_widget(main_window,
2401                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2402         if (!header_view)
2403                 return;
2404         
2405         conf = modest_runtime_get_conf ();
2406
2407         if (TNY_IS_ACCOUNT (folder_store)) {
2408                 if (selected) {
2409                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2410                         
2411                         /* Show account details */
2412                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2413                 }
2414         } else {
2415                 if (TNY_IS_FOLDER (folder_store) && selected) {
2416                         TnyAccount *account;
2417                         const gchar *account_name = NULL;
2418                         gboolean refresh;
2419
2420                         /* Update the active account */
2421                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2422                         if (account) {
2423                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2424                                 account_name = 
2425                                         modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2426                                 g_object_unref (account);
2427                                 account = NULL;
2428                         }
2429
2430                         /* Set the header style by default, it could
2431                            be changed later by the refresh callback to
2432                            empty */
2433                         modest_main_window_set_contents_style (main_window, 
2434                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2435
2436                         refresh = !modest_account_mgr_account_is_busy (modest_runtime_get_account_mgr (), account_name);
2437
2438                         /* Set folder on header view. This function
2439                            will call tny_folder_refresh_async so we
2440                            pass a callback that will be called when
2441                            finished. We use that callback to set the
2442                            empty view if there are no messages */
2443                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2444                                                        TNY_FOLDER (folder_store),
2445                                                        refresh,
2446                                                        folder_refreshed_cb,
2447                                                        main_window);
2448                         
2449                         /* Restore configuration. We need to do this
2450                            *after* the set_folder because the widget
2451                            memory asks the header view about its
2452                            folder  */
2453                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2454                                                       G_OBJECT(header_view),
2455                                                       MODEST_CONF_HEADER_VIEW_KEY);
2456                 } else {
2457                         /* No need to save the header view
2458                            configuration for Maemo because it only
2459                            saves the sorting stuff and that it's
2460                            already being done by the sort
2461                            dialog. Remove it when the GNOME version
2462                            has the same behaviour */
2463 #ifdef MODEST_PLATFORM_GNOME
2464                         if (modest_main_window_get_contents_style (main_window) ==
2465                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2466                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2467                                                            MODEST_CONF_HEADER_VIEW_KEY);
2468 #endif
2469                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2470                 }
2471         }
2472
2473         /* Update dimming state */
2474         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2475         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2476 }
2477
2478 void 
2479 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2480                                      ModestWindow *win)
2481 {
2482         GtkWidget *dialog;
2483         gchar *txt, *item;
2484         gboolean online;
2485
2486         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2487         
2488         online = tny_device_is_online (modest_runtime_get_device());
2489
2490         if (online) {
2491                 /* already online -- the item is simply not there... */
2492                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2493                                                  GTK_DIALOG_MODAL,
2494                                                  GTK_MESSAGE_WARNING,
2495                                                  GTK_BUTTONS_NONE,
2496                                                  _("The %s you selected cannot be found"),
2497                                                  item);
2498                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2499                 gtk_dialog_run (GTK_DIALOG(dialog));
2500         } else {
2501                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2502                                                       GTK_WINDOW (win),
2503                                                       GTK_DIALOG_MODAL,
2504                                                       _("mcen_bd_dialog_cancel"),
2505                                                       GTK_RESPONSE_REJECT,
2506                                                       _("mcen_bd_dialog_ok"),
2507                                                       GTK_RESPONSE_ACCEPT,
2508                                                       NULL);
2509                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2510                                          "Do you want to get online?"), item);
2511                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2512                                     gtk_label_new (txt), FALSE, FALSE, 0);
2513                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2514                 g_free (txt);
2515
2516                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2517                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2518                         /* TODO: Comment about why is this commented out: */
2519                         /* modest_platform_connect_and_wait (); */
2520                 }
2521         }
2522         gtk_widget_destroy (dialog);
2523 }
2524
2525 void
2526 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2527                                      ModestWindow *win)
2528 {
2529         /* g_message ("%s %s", __FUNCTION__, link); */
2530 }       
2531
2532
2533 void
2534 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2535                                         ModestWindow *win)
2536 {
2537         modest_platform_activate_uri (link);
2538 }
2539
2540 void
2541 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2542                                           ModestWindow *win)
2543 {
2544         modest_platform_show_uri_popup (link);
2545 }
2546
2547 void
2548 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2549                                              ModestWindow *win)
2550 {               
2551         /* we check for low-mem; in that case, show a warning, and don't allow
2552          * viewing attachments
2553          */
2554         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2555                 return;
2556
2557         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2558 }
2559
2560 void
2561 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2562                                           const gchar *address,
2563                                           ModestWindow *win)
2564 {
2565         /* g_message ("%s %s", __FUNCTION__, address); */
2566 }
2567
2568 static void
2569 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2570                       TnyMsg *saved_draft,
2571                       gpointer user_data)
2572 {
2573         ModestMsgEditWindow *edit_window;
2574         ModestMainWindow *win;
2575
2576         /* FIXME. Make the header view sensitive again. This is a
2577          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2578          * for details */
2579         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2580                                          modest_runtime_get_window_mgr(), FALSE));
2581         if (win != NULL) {
2582                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2583                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2584                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2585         }
2586
2587         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2588
2589         /* Set draft is there was no error */
2590         if (!modest_mail_operation_get_error (mail_op))
2591                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2592
2593         g_object_unref(edit_window);
2594 }
2595
2596 gboolean
2597 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2598 {
2599         TnyTransportAccount *transport_account;
2600         ModestMailOperation *mail_operation;
2601         MsgData *data;
2602         gchar *account_name, *from;
2603         ModestAccountMgr *account_mgr;
2604 /*      char *info_text; */
2605         gboolean had_error = FALSE;
2606         guint64 available_disk, expected_size;
2607         gint parts_count;
2608         guint64 parts_size;
2609         ModestMainWindow *win;
2610
2611         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2612         
2613         data = modest_msg_edit_window_get_msg_data (edit_window);
2614
2615         /* Check size */
2616         available_disk = modest_folder_available_space (NULL);
2617         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2618         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2619                                                  data->html_body,
2620                                                  parts_count,
2621                                                  parts_size);
2622
2623         if ((available_disk != -1) && expected_size > available_disk) {
2624                 modest_msg_edit_window_free_msg_data (edit_window, data);
2625
2626                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2627                 return FALSE;
2628         }
2629
2630         /*
2631          * djcb: if we're in low-memory state, we only allow for
2632          * saving messages smaller than
2633          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2634          * should still allow for sending anything critical...
2635          */
2636         if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2637
2638                 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE)) {
2639                         modest_msg_edit_window_free_msg_data (edit_window, data);
2640                         return FALSE;
2641                 }
2642         }
2643
2644         /*
2645          * djcb: we also make sure that the attachments are smaller than the max size
2646          * this is for the case where we'd try to forward a message with attachments 
2647          * bigger than our max allowed size, or sending an message from drafts which
2648          * somehow got past our checks when attaching.
2649          */
2650         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2651                 modest_platform_run_information_dialog (
2652                         GTK_WINDOW(edit_window),
2653                         dgettext("ke-recv","memr_ib_operation_disabled"),
2654                         TRUE);
2655                 modest_msg_edit_window_free_msg_data (edit_window, data);
2656                 return FALSE;
2657         }
2658
2659         account_name = g_strdup (data->account_name);
2660         account_mgr = modest_runtime_get_account_mgr();
2661         if (!account_name)
2662                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2663         if (!account_name) 
2664                 account_name = modest_account_mgr_get_default_account (account_mgr);
2665         if (!account_name) {
2666                 g_printerr ("modest: no account found\n");
2667                 modest_msg_edit_window_free_msg_data (edit_window, data);
2668                 return FALSE;
2669         }
2670
2671         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2672                 account_name = g_strdup (data->account_name);
2673         }
2674
2675         transport_account =
2676                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2677                                       (modest_runtime_get_account_store(),
2678                                        account_name,
2679                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2680         if (!transport_account) {
2681                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2682                 g_free (account_name);
2683                 modest_msg_edit_window_free_msg_data (edit_window, data);
2684                 return FALSE;
2685         }
2686         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2687
2688         /* Create the mail operation */         
2689         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2690                                                                         NULL, NULL);
2691         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2692
2693         modest_mail_operation_save_to_drafts (mail_operation,
2694                                               transport_account,
2695                                               data->draft_msg,
2696                                               from,
2697                                               data->to, 
2698                                               data->cc, 
2699                                               data->bcc,
2700                                               data->subject, 
2701                                               data->plain_body, 
2702                                               data->html_body,
2703                                               data->attachments,
2704                                               data->images,
2705                                               data->priority_flags,
2706                                               on_save_to_drafts_cb,
2707                                               g_object_ref(edit_window));
2708
2709         /* Use the main window as the parent of the banner, if the
2710            main window does not exist it won't be shown, if the parent
2711            window exists then it's properly shown. We don't use the
2712            editor window because it could be closed (save to drafts
2713            could happen after closing the window */
2714         win = (ModestMainWindow *)
2715                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2716         if (win) {
2717                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2718                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2719                 g_free (text);
2720         }
2721         modest_msg_edit_window_set_modified (edit_window, FALSE);
2722
2723         /* Frees */
2724         g_free (from);
2725         g_free (account_name);
2726         g_object_unref (G_OBJECT (transport_account));
2727         g_object_unref (G_OBJECT (mail_operation));
2728
2729         modest_msg_edit_window_free_msg_data (edit_window, data);
2730
2731         /* ** FIXME **
2732          * If the drafts folder is selected then make the header view
2733          * insensitive while the message is being saved to drafts
2734          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2735          * is not very clean but it avoids letting the drafts folder
2736          * in an inconsistent state: the user could edit the message
2737          * being saved and undesirable things would happen.
2738          * In the average case the user won't notice anything at
2739          * all. In the worst case (the user is editing a really big
2740          * file from Drafts) the header view will be insensitive
2741          * during the saving process (10 or 20 seconds, depending on
2742          * the message). Anyway this is just a quick workaround: once
2743          * we find a better solution it should be removed
2744          * See NB#65125 (commend #18) for details.
2745          */
2746         if (!had_error && win != NULL) {
2747                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2748                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2749                 if (view != NULL) {
2750                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2751                         if (folder) {
2752                                 if (modest_tny_folder_is_local_folder(folder)) {
2753                                         TnyFolderType folder_type;
2754                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2755                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2756                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2757                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2758                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2759                                         }
2760                                 }
2761                         }
2762                         if (folder != NULL) g_object_unref(folder);
2763                 }
2764         }
2765
2766         return !had_error;
2767 }
2768
2769 /* For instance, when clicking the Send toolbar button when editing a message: */
2770 gboolean
2771 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2772 {
2773         TnyTransportAccount *transport_account = NULL;
2774         gboolean had_error = FALSE;
2775         guint64 available_disk, expected_size;
2776         gint parts_count;
2777         guint64 parts_size;
2778
2779         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2780
2781         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2782                 return TRUE;
2783         
2784         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2785
2786         /* Check size */
2787         available_disk = modest_folder_available_space (NULL);
2788         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2789         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2790                                                  data->html_body,
2791                                                  parts_count,
2792                                                  parts_size);
2793
2794         if ((available_disk != -1) && expected_size > available_disk) {
2795                 modest_msg_edit_window_free_msg_data (edit_window, data);
2796
2797                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2798                 return FALSE;
2799         }
2800
2801         
2802         /*
2803          * djcb: if we're in low-memory state, we only allow for sending messages
2804          * smaller than MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h)
2805          * this should still allow for sending anything critical... 
2806          */
2807         if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2808                 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE)) {
2809                         modest_msg_edit_window_free_msg_data (edit_window, data);
2810                         return FALSE;
2811                 }
2812         }
2813
2814         /*
2815          * djcb: we also make sure that the attachments are smaller than the max size
2816          * this is for the case where we'd try to forward a message with attachments 
2817          * bigger than our max allowed size, or sending an message from drafts which
2818          * somehow got past our checks when attaching.
2819          */
2820         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2821                 modest_platform_run_information_dialog (
2822                         GTK_WINDOW(edit_window),
2823                         dgettext("ke-recv","memr_ib_operation_disabled"),
2824                         TRUE);
2825                 modest_msg_edit_window_free_msg_data (edit_window, data);
2826                 return FALSE;
2827         }
2828
2829         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2830         gchar *account_name = g_strdup (data->account_name);
2831         if (!account_name)
2832                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2833
2834         if (!account_name) 
2835                 account_name = modest_account_mgr_get_default_account (account_mgr);
2836                 
2837         if (!account_name) {
2838                 modest_msg_edit_window_free_msg_data (edit_window, data);
2839                 /* Run account setup wizard */
2840                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2841                         return TRUE;
2842                 }
2843         }
2844         
2845         /* Get the currently-active transport account for this modest account: */
2846         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2847                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2848                                                           (modest_runtime_get_account_store(),
2849                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2850         }
2851         
2852         if (!transport_account) {
2853                 modest_msg_edit_window_free_msg_data (edit_window, data);
2854                 /* Run account setup wizard */
2855                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2856                         return TRUE;
2857         }
2858         
2859         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2860
2861         /* Create the mail operation */
2862         ModestMailOperation *mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
2863         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2864
2865         modest_mail_operation_send_new_mail (mail_operation,
2866                                              transport_account,
2867                                              data->draft_msg,
2868                                              from,
2869                                              data->to, 
2870                                              data->cc, 
2871                                              data->bcc,
2872                                              data->subject, 
2873                                              data->plain_body, 
2874                                              data->html_body,
2875                                              data->attachments,
2876                                              data->images,
2877                                              data->priority_flags);
2878
2879         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2880                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2881
2882
2883         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2884                 const GError *error = modest_mail_operation_get_error (mail_operation);
2885                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
2886                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2887                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2888                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2889                         had_error = TRUE;
2890                 }
2891         }
2892                                              
2893         /* Free data: */
2894         g_free (from);
2895         g_free (account_name);
2896         g_object_unref (G_OBJECT (transport_account));
2897         g_object_unref (G_OBJECT (mail_operation));
2898
2899         modest_msg_edit_window_free_msg_data (edit_window, data);
2900
2901         if (!had_error) {
2902                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2903
2904                 /* Save settings and close the window: */
2905                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2906         }
2907
2908         return !had_error;
2909 }
2910
2911 void 
2912 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2913                                   ModestMsgEditWindow *window)
2914 {
2915         ModestMsgEditFormatState *format_state = NULL;
2916
2917         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2918         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2919
2920         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2921                 return;
2922
2923         format_state = modest_msg_edit_window_get_format_state (window);
2924         g_return_if_fail (format_state != NULL);
2925
2926         format_state->bold = gtk_toggle_action_get_active (action);
2927         modest_msg_edit_window_set_format_state (window, format_state);
2928         g_free (format_state);
2929         
2930 }
2931
2932 void 
2933 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2934                                      ModestMsgEditWindow *window)
2935 {
2936         ModestMsgEditFormatState *format_state = NULL;
2937
2938         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2939         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2940
2941         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2942                 return;
2943
2944         format_state = modest_msg_edit_window_get_format_state (window);
2945         g_return_if_fail (format_state != NULL);
2946
2947         format_state->italics = gtk_toggle_action_get_active (action);
2948         modest_msg_edit_window_set_format_state (window, format_state);
2949         g_free (format_state);
2950         
2951 }
2952
2953 void 
2954 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2955                                      ModestMsgEditWindow *window)
2956 {
2957         ModestMsgEditFormatState *format_state = NULL;
2958
2959         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2960         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2961
2962         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2963                 return;
2964
2965         format_state = modest_msg_edit_window_get_format_state (window);
2966         g_return_if_fail (format_state != NULL);
2967
2968         format_state->bullet = gtk_toggle_action_get_active (action);
2969         modest_msg_edit_window_set_format_state (window, format_state);
2970         g_free (format_state);
2971         
2972 }
2973
2974 void 
2975 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2976                                      GtkRadioAction *selected,
2977                                      ModestMsgEditWindow *window)
2978 {
2979         ModestMsgEditFormatState *format_state = NULL;
2980         GtkJustification value;
2981
2982         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2983
2984         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2985                 return;
2986
2987         value = gtk_radio_action_get_current_value (selected);
2988
2989         format_state = modest_msg_edit_window_get_format_state (window);
2990         g_return_if_fail (format_state != NULL);
2991
2992         format_state->justification = value;
2993         modest_msg_edit_window_set_format_state (window, format_state);
2994         g_free (format_state);
2995 }
2996
2997 void 
2998 modest_ui_actions_on_select_editor_color (GtkAction *action,
2999                                           ModestMsgEditWindow *window)
3000 {
3001         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3002         g_return_if_fail (GTK_IS_ACTION (action));
3003
3004         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3005                 return;
3006
3007         modest_msg_edit_window_select_color (window);
3008 }
3009
3010 void 
3011 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3012                                                      ModestMsgEditWindow *window)
3013 {
3014         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3015         g_return_if_fail (GTK_IS_ACTION (action));
3016
3017         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3018                 return;
3019
3020         modest_msg_edit_window_select_background_color (window);
3021 }
3022
3023 void 
3024 modest_ui_actions_on_insert_image (GtkAction *action,
3025                                    ModestMsgEditWindow *window)
3026 {
3027         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3028         g_return_if_fail (GTK_IS_ACTION (action));
3029
3030
3031         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3032                 return;
3033
3034         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3035                 return;
3036
3037         modest_msg_edit_window_insert_image (window);
3038 }
3039
3040 void 
3041 modest_ui_actions_on_attach_file (GtkAction *action,
3042                                   ModestMsgEditWindow *window)
3043 {
3044         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3045         g_return_if_fail (GTK_IS_ACTION (action));
3046
3047         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3048                 return;
3049         
3050         modest_msg_edit_window_offer_attach_file (window);
3051 }
3052
3053 void 
3054 modest_ui_actions_on_remove_attachments (GtkAction *action,
3055                                          ModestMsgEditWindow *window)
3056 {
3057         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3058         g_return_if_fail (GTK_IS_ACTION (action));
3059
3060         modest_msg_edit_window_remove_attachments (window, NULL);
3061 }
3062
3063
3064 #ifdef MODEST_PLATFORM_MAEMO
3065 typedef struct {
3066         guint handler;
3067         gchar *name;
3068         GtkWindow *win;
3069         TnyFolderStore *folder;
3070 } CreateFolderHelper;
3071
3072 static gboolean
3073 show_create_folder_in_timeout (gpointer data)
3074 {
3075         CreateFolderHelper *helper = (CreateFolderHelper *) data;
3076
3077         /* Remove the timeout ASAP, we can not wait until the dialog
3078            is shown because it could take a lot of time and so the
3079            timeout could be called twice or more times */
3080         g_source_remove (helper->handler);
3081
3082         gdk_threads_enter ();
3083         do_create_folder (helper->win, helper->folder, helper->name);
3084         gdk_threads_leave ();
3085
3086         g_object_unref (helper->win);
3087         g_object_unref (helper->folder);
3088         g_free (helper->name);
3089         g_slice_free (CreateFolderHelper, helper);
3090
3091         return FALSE;
3092 }
3093 #endif
3094
3095 static void
3096 do_create_folder_cb (ModestMailOperation *mail_op,
3097                      TnyFolderStore *parent_folder, 
3098                      TnyFolder *new_folder,
3099                      gpointer user_data)
3100 {
3101         gchar *suggested_name = (gchar *) user_data;
3102         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3103
3104         if (modest_mail_operation_get_error (mail_op)) {
3105
3106                 /* Show an error. If there was some problem writing to
3107                    disk, show it, otherwise show the generic folder
3108                    create error. We do it here and not in an error
3109                    handler because the call to do_create_folder will
3110                    stop the main loop in a gtk_dialog_run and then,
3111                    the message won't be shown until that dialog is
3112                    closed */
3113                 modest_ui_actions_disk_operations_error_handler (mail_op,
3114                                                                  _("mail_in_ui_folder_create_error"));
3115
3116                 /* Try again. Do *NOT* show any error because the mail
3117                    operations system will do it for us because we
3118                    created the mail_op with new_with_error_handler */
3119 #ifdef MODEST_PLATFORM_MAEMO
3120                 CreateFolderHelper *helper;
3121                 helper = g_slice_new0 (CreateFolderHelper);
3122                 helper->name = g_strdup (suggested_name);
3123                 helper->folder = g_object_ref (parent_folder);
3124                 helper->win = g_object_ref (source_win);
3125
3126                 /* Ugly but neccesary stuff. The problem is that the
3127                    dialog when is shown calls a function that destroys
3128                    all the temporary windows, so the banner is
3129                    destroyed */
3130                 helper->handler = g_timeout_add (2000, show_create_folder_in_timeout, helper);
3131 #else
3132                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3133 #endif
3134         } else {
3135                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3136                  * FIXME: any other? */         
3137                 GtkWidget *folder_view;
3138
3139                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
3140                         folder_view = 
3141                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3142                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3143                 else
3144                         folder_view =
3145                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
3146                 
3147                 /* Select the newly created folder. It could happen
3148                    that the widget is no longer there (i.e. the window
3149                    has been destroyed, so we need to check this */
3150                 if (folder_view)
3151                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3152                                                           new_folder, FALSE);
3153                 g_object_unref (new_folder);
3154         }
3155         /* Free. Note that the first time it'll be NULL so noop */
3156         g_free (suggested_name);
3157         g_object_unref (source_win);
3158 }
3159
3160 static void
3161 do_create_folder (GtkWindow *parent_window, 
3162                   TnyFolderStore *parent_folder, 
3163                   const gchar *suggested_name)
3164 {
3165         gint result;
3166         gchar *folder_name = NULL;
3167
3168         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3169                                                         parent_folder,
3170                                                         (gchar *) suggested_name,
3171                                                         &folder_name);
3172         
3173         if (result == GTK_RESPONSE_ACCEPT) {
3174                 ModestMailOperation *mail_op;
3175                 
3176                 mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3177                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3178                                                  mail_op);
3179                 modest_mail_operation_create_folder (mail_op,
3180                                                      parent_folder,
3181                                                      (const gchar *) folder_name,
3182                                                      do_create_folder_cb,
3183                                                      folder_name);
3184                 g_object_unref (mail_op);
3185         }
3186 }
3187
3188 static void
3189 create_folder_performer (gboolean canceled, 
3190                          GError *err,
3191                          GtkWindow *parent_window, 
3192                          TnyAccount *account, 
3193                          gpointer user_data)
3194 {
3195         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3196
3197         if (canceled || err) {
3198                 /* In memory full conditions we could get this error here */
3199                 check_memory_full_error ((GtkWidget *) parent_window, err);
3200                 goto frees;
3201         }
3202
3203         /* Run the new folder dialog */
3204         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3205
3206  frees:
3207         g_object_unref (parent_folder);
3208 }
3209
3210 static void
3211 modest_ui_actions_create_folder(GtkWidget *parent_window,
3212                                 GtkWidget *folder_view)
3213 {
3214         TnyFolderStore *parent_folder;
3215
3216         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3217         
3218         if (parent_folder) {
3219                 /* The parent folder will be freed in the callback */
3220                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
3221                                                                TRUE,
3222                                                                parent_folder,
3223                                                                create_folder_performer, 
3224                                                                parent_folder);
3225         }
3226 }
3227
3228 void 
3229 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3230 {
3231         GtkWidget *folder_view;
3232         
3233         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3234
3235         folder_view = modest_main_window_get_child_widget (main_window,
3236                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3237         if (!folder_view)
3238                 return;
3239
3240         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3241 }
3242
3243 static void
3244 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3245                                                gpointer user_data)
3246 {
3247         const GError *error = NULL;
3248         const gchar *message = NULL;
3249         
3250         /* Get error message */
3251         error = modest_mail_operation_get_error (mail_op);
3252         if (!error)
3253                 g_return_if_reached ();
3254
3255         if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3256             error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3257                 message = _CS("ckdg_ib_folder_already_exists");
3258         } else if (error->domain == TNY_ERROR_DOMAIN &&
3259                    error->code == TNY_SERVICE_ERROR_STATE) {
3260                 /* This means that the folder is already in use (a
3261                    message is opened for example */
3262                 message = _("emev_ni_internal_error");
3263         } else {
3264                 message = _("emev_ib_ui_imap_unable_to_rename");
3265         }
3266
3267         /* We don't set a parent for the dialog because the dialog
3268            will be destroyed so the banner won't appear */
3269         modest_platform_information_banner (NULL, NULL, message);
3270 }
3271
3272 typedef struct {
3273         TnyFolderStore *folder;
3274         gchar *new_name;
3275 } RenameFolderInfo;
3276
3277 static void
3278 on_rename_folder_cb (ModestMailOperation *mail_op, 
3279                      TnyFolder *new_folder,
3280                      gpointer user_data)
3281 {
3282         ModestFolderView *folder_view;
3283
3284         /* If the window was closed when renaming a folder this could
3285            happen */
3286         if (!MODEST_IS_FOLDER_VIEW (user_data))
3287                 return;
3288
3289         folder_view = MODEST_FOLDER_VIEW (user_data);
3290         /* Note that if the rename fails new_folder will be NULL */
3291         if (new_folder) {
3292                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3293         } else {
3294                 modest_folder_view_select_first_inbox_or_local (folder_view);
3295         }
3296         gtk_widget_grab_focus (GTK_WIDGET (folder_view));       
3297 }
3298
3299 static void
3300 on_rename_folder_performer (gboolean canceled, 
3301                             GError *err, 
3302                             GtkWindow *parent_window, 
3303                             TnyAccount *account, 
3304                             gpointer user_data)
3305 {
3306         ModestMailOperation *mail_op = NULL;
3307         GtkTreeSelection *sel = NULL;
3308         GtkWidget *folder_view = NULL;
3309         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3310
3311         if (canceled || err) {
3312                 /* In memory full conditions we could get this error here */
3313                 check_memory_full_error ((GtkWidget *) parent_window, err);
3314         } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3315
3316                 folder_view = modest_main_window_get_child_widget (
3317                                 MODEST_MAIN_WINDOW (parent_window),
3318                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3319
3320                 mail_op = 
3321                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3322                                         modest_ui_actions_rename_folder_error_handler,
3323                                         parent_window, NULL);
3324
3325                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3326                                 mail_op);
3327
3328                 /* Clear the headers view */
3329                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3330                 gtk_tree_selection_unselect_all (sel);
3331
3332                 /* Actually rename the folder */
3333                 modest_mail_operation_rename_folder (mail_op,
3334                                                      TNY_FOLDER (data->folder),
3335                                                      (const gchar *) (data->new_name),
3336                                                      on_rename_folder_cb,
3337                                                      folder_view);
3338                 g_object_unref (mail_op);
3339         }
3340
3341         g_free (data->new_name);
3342         g_free (data);
3343 }
3344
3345 void 
3346 modest_ui_actions_on_rename_folder (GtkAction *action,
3347                                      ModestMainWindow *main_window)
3348 {
3349         TnyFolderStore *folder;
3350         GtkWidget *folder_view;
3351         GtkWidget *header_view; 
3352
3353         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3354
3355         folder_view = modest_main_window_get_child_widget (main_window,
3356                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3357         if (!folder_view)
3358                 return;
3359
3360         header_view = modest_main_window_get_child_widget (main_window,
3361                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3362         
3363         if (!header_view)
3364                 return;
3365
3366         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3367
3368         if (!folder)
3369                 return;
3370
3371         if (TNY_IS_FOLDER (folder)) {
3372                 gchar *folder_name;
3373                 gint response;
3374                 const gchar *current_name;
3375                 TnyFolderStore *parent;
3376                 gboolean do_rename = TRUE;
3377
3378                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3379                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3380                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
3381                                                                      parent, current_name, 
3382                                                                      &folder_name);
3383                 g_object_unref (parent);
3384
3385                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3386                         do_rename = FALSE;
3387                 } else {
3388                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3389                         rename_folder_data->folder = folder;
3390                         rename_folder_data->new_name = folder_name;
3391                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3392                                         folder, on_rename_folder_performer, rename_folder_data);
3393                 }
3394         }
3395         g_object_unref (folder);
3396 }
3397
3398 static void
3399 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3400                                                gpointer user_data)
3401 {
3402         GObject *win = modest_mail_operation_get_source (mail_op);
3403
3404         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3405                                                 _("mail_in_ui_folder_delete_error"),
3406                                                 FALSE);
3407         g_object_unref (win);
3408 }
3409
3410 typedef struct {
3411         TnyFolderStore *folder;
3412         gboolean move_to_trash;
3413 } DeleteFolderInfo;
3414
3415 static void
3416 on_delete_folder_cb (gboolean canceled, 
3417                   GError *err,
3418                   GtkWindow *parent_window, 
3419                   TnyAccount *account, 
3420                   gpointer user_data)
3421 {
3422         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3423         GtkWidget *folder_view;
3424         ModestMailOperation *mail_op;
3425         GtkTreeSelection *sel;
3426         
3427         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3428                 g_object_unref (G_OBJECT (info->folder));
3429                 g_free (info);
3430                 return;
3431         }
3432         
3433         folder_view = modest_main_window_get_child_widget (
3434                         MODEST_MAIN_WINDOW (parent_window),
3435                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3436
3437         /* Unselect the folder before deleting it to free the headers */
3438         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3439         gtk_tree_selection_unselect_all (sel);
3440
3441         /* Create the mail operation */
3442         mail_op =
3443                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3444                                 modest_ui_actions_delete_folder_error_handler,
3445                                 NULL, NULL);
3446
3447         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3448                         mail_op);
3449         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3450         
3451         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3452
3453         g_object_unref (G_OBJECT (mail_op));
3454         g_object_unref (G_OBJECT (info->folder));
3455         g_free (info);
3456 }
3457
3458 static void
3459 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3460 {
3461         TnyFolderStore *folder;
3462         GtkWidget *folder_view;
3463         gint response;
3464         gchar *message;
3465         
3466         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3467
3468         folder_view = modest_main_window_get_child_widget (main_window,
3469                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3470         if (!folder_view)
3471                 return;
3472
3473         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3474
3475         /* Show an error if it's an account */
3476         if (!TNY_IS_FOLDER (folder)) {
3477                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3478                                                         _("mail_in_ui_folder_delete_error"),
3479                                                         FALSE);
3480                 g_object_unref (G_OBJECT (folder));
3481                 return;
3482         }
3483
3484         /* Ask the user */      
3485         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3486                                     tny_folder_get_name (TNY_FOLDER (folder)));
3487         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3488                                                             (const gchar *) message);
3489         g_free (message);
3490
3491         if (response == GTK_RESPONSE_OK) {
3492                 DeleteFolderInfo *info;
3493                 info = g_new0(DeleteFolderInfo, 1);
3494                 info->folder = folder;
3495                 info->move_to_trash = move_to_trash;
3496                 g_object_ref (G_OBJECT (info->folder));
3497                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3498                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3499                                                                TRUE,
3500                                                                TNY_FOLDER_STORE (account), 
3501                                                                on_delete_folder_cb, info);
3502                 g_object_unref (account);
3503         }
3504         g_object_unref (G_OBJECT (folder));
3505 }
3506
3507 void 
3508 modest_ui_actions_on_delete_folder (GtkAction *action,
3509                                      ModestMainWindow *main_window)
3510 {
3511         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3512         
3513         delete_folder (main_window, FALSE);
3514 }
3515
3516 void 
3517 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3518 {
3519         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3520         
3521         delete_folder (main_window, TRUE);
3522 }
3523
3524
3525 typedef struct _PasswordDialogFields {
3526         GtkWidget *username;
3527         GtkWidget *password;
3528         GtkWidget *dialog;
3529 } PasswordDialogFields;
3530
3531 static void
3532 password_dialog_check_field (GtkEditable *editable,
3533                              PasswordDialogFields *fields)
3534 {
3535         const gchar *value;
3536         gboolean any_value_empty = FALSE;
3537
3538         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3539         if ((value == NULL) || value[0] == '\0') {
3540                 any_value_empty = TRUE;
3541         }
3542         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3543         if ((value == NULL) || value[0] == '\0') {
3544                 any_value_empty = TRUE;
3545         }
3546         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3547 }
3548
3549 void
3550 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3551                                          const gchar* server_account_name,
3552                                          gchar **username,
3553                                          gchar **password, 
3554                                          gboolean *cancel, 
3555                                          gboolean *remember,
3556                                          ModestMainWindow *main_window)
3557 {
3558         g_return_if_fail(server_account_name);
3559         gboolean completed = FALSE;
3560         PasswordDialogFields *fields = NULL;
3561         
3562         /* Initalize output parameters: */
3563         if (cancel)
3564                 *cancel = FALSE;
3565                 
3566         if (remember)
3567                 *remember = TRUE;
3568                 
3569 #ifdef MODEST_PLATFORM_MAEMO
3570         /* Maemo uses a different (awkward) button order,
3571          * It should probably just use gtk_alternative_dialog_button_order ().
3572          */
3573         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3574                                               NULL,
3575                                               GTK_DIALOG_MODAL,
3576                                               _("mcen_bd_dialog_ok"),
3577                                               GTK_RESPONSE_ACCEPT,
3578                                               _("mcen_bd_dialog_cancel"),
3579                                               GTK_RESPONSE_REJECT,
3580                                               NULL);
3581 #else
3582         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3583                                               NULL,
3584                                               GTK_DIALOG_MODAL,
3585                                               GTK_STOCK_CANCEL,
3586                                               GTK_RESPONSE_REJECT,
3587                                               GTK_STOCK_OK,
3588                                               GTK_RESPONSE_ACCEPT,
3589                                               NULL);
3590 #endif /* MODEST_PLATFORM_MAEMO */
3591
3592         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3593         
3594         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3595                 modest_runtime_get_account_mgr(), server_account_name);
3596         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3597                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3598                 if (cancel)
3599                         *cancel = TRUE;
3600                 return;
3601         }
3602         
3603         /* This causes a warning because the logical ID has no %s in it, 
3604          * though the translation does, but there is not much we can do about that: */
3605         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3606         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3607                             FALSE, FALSE, 0);
3608         g_free (txt);
3609         g_free (server_name);
3610         server_name = NULL;
3611
3612         /* username: */
3613         gchar *initial_username = modest_account_mgr_get_server_account_username (
3614                 modest_runtime_get_account_mgr(), server_account_name);
3615         
3616         GtkWidget *entry_username = gtk_entry_new ();
3617         if (initial_username)
3618                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3619         /* Dim this if a connection has ever succeeded with this username,
3620          * as per the UI spec: */
3621         /* const gboolean username_known =  */
3622         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3623         /*              modest_runtime_get_account_mgr(), server_account_name); */
3624         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3625
3626         /* We drop the username sensitive code and disallow changing it here
3627          * as tinymail does not support really changing the username in the callback
3628          */
3629         gtk_widget_set_sensitive (entry_username, FALSE);
3630
3631 #ifdef MODEST_PLATFORM_MAEMO
3632         /* Auto-capitalization is the default, so let's turn it off: */
3633         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3634         
3635         /* Create a size group to be used by all captions.
3636          * Note that HildonCaption does not create a default size group if we do not specify one.
3637          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3638         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3639         
3640         GtkWidget *caption = hildon_caption_new (sizegroup, 
3641                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3642         gtk_widget_show (entry_username);
3643         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3644                 FALSE, FALSE, MODEST_MARGIN_HALF);
3645         gtk_widget_show (caption);
3646 #else 
3647         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3648                             TRUE, FALSE, 0);
3649 #endif /* MODEST_PLATFORM_MAEMO */      
3650                             
3651         /* password: */
3652         GtkWidget *entry_password = gtk_entry_new ();
3653         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3654         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3655         
3656 #ifdef MODEST_PLATFORM_MAEMO
3657         /* Auto-capitalization is the default, so let's turn it off: */
3658         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3659                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3660         
3661         caption = hildon_caption_new (sizegroup, 
3662                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3663         gtk_widget_show (entry_password);
3664         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3665                 FALSE, FALSE, MODEST_MARGIN_HALF);
3666         gtk_widget_show (caption);
3667         g_object_unref (sizegroup);
3668 #else 
3669         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3670                             TRUE, FALSE, 0);
3671 #endif /* MODEST_PLATFORM_MAEMO */      
3672
3673         if (initial_username != NULL)
3674                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3675                                 
3676 /* This is not in the Maemo UI spec:
3677         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3678         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3679                             TRUE, FALSE, 0);
3680 */
3681
3682         fields = g_slice_new0 (PasswordDialogFields);
3683         fields->username = entry_username;
3684         fields->password = entry_password;
3685         fields->dialog = dialog;
3686
3687         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3688         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3689         password_dialog_check_field (NULL, fields);
3690
3691         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3692
3693         while (!completed) {
3694         
3695                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3696                         if (username) {
3697                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3698                                 
3699                                 /* Note that an empty field becomes the "" string */
3700                                 if (*username && strlen (*username) > 0) {
3701                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3702                                                                                         server_account_name, 
3703                                                                                         *username);
3704                                         completed = TRUE;
3705                                 
3706                                         const gboolean username_was_changed = 
3707                                                 (strcmp (*username, initial_username) != 0);
3708                                         if (username_was_changed) {
3709                                                 g_warning ("%s: tinymail does not yet support changing the "
3710                                                            "username in the get_password() callback.\n", __FUNCTION__);
3711                                         }
3712                                 } else {
3713                                         /* Show error */
3714                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3715                                                                             _("mcen_ib_username_pw_incorrect"));
3716                                         completed = FALSE;
3717                                 }
3718                         }
3719                         
3720                         if (password) {
3721                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3722                         
3723                                 /* We do not save the password in the configuration, 
3724                                  * because this function is only called for passwords that should 
3725                                  * not be remembered:
3726                                  modest_server_account_set_password (
3727                                  modest_runtime_get_account_mgr(), server_account_name, 
3728                                  *password);
3729                                  */
3730                         }                       
3731                         if (cancel)
3732                                 *cancel   = FALSE;                      
3733                 } else {
3734                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3735                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3736                         completed = TRUE;
3737                         if (username)
3738                                 *username = NULL;                       
3739                         if (password)
3740                                 *password = NULL;                       
3741                         if (cancel)
3742                                 *cancel   = TRUE;
3743                 }
3744         }
3745
3746 /* This is not in the Maemo UI spec:
3747         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3748                 *remember = TRUE;
3749         else
3750                 *remember = FALSE;
3751 */
3752
3753         gtk_widget_destroy (dialog);
3754         g_slice_free (PasswordDialogFields, fields);
3755         
3756         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3757 }
3758
3759 void
3760 modest_ui_actions_on_cut (GtkAction *action,
3761                           ModestWindow *window)
3762 {
3763         GtkWidget *focused_widget;
3764         GtkClipboard *clipboard;
3765
3766         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3767         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3768         if (GTK_IS_EDITABLE (focused_widget)) {
3769                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3770                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3771                 gtk_clipboard_store (clipboard);
3772         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3773                 GtkTextBuffer *buffer;
3774
3775                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3776                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3777                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3778                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3779                         gtk_clipboard_store (clipboard);
3780                 }
3781         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3782                 TnyList *header_list = modest_header_view_get_selected_headers (
3783                                 MODEST_HEADER_VIEW (focused_widget));
3784                 gboolean continue_download = FALSE;
3785                 gint num_of_unc_msgs;
3786
3787                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3788
3789                 if (num_of_unc_msgs) {
3790                         TnyAccount *account = get_account_from_header_list (header_list);
3791                         if (account) {
3792                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3793                                 g_object_unref (account);
3794                         }
3795                 }
3796
3797                 if (num_of_unc_msgs == 0 || continue_download) {
3798 /*                      modest_platform_information_banner (
3799                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3800                         modest_header_view_cut_selection (
3801                                         MODEST_HEADER_VIEW (focused_widget));
3802                 }
3803
3804                 g_object_unref (header_list);
3805         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3806                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3807         }
3808 }
3809
3810 void
3811 modest_ui_actions_on_copy (GtkAction *action,
3812                            ModestWindow *window)
3813 {
3814         GtkClipboard *clipboard;
3815         GtkWidget *focused_widget;
3816         gboolean copied = TRUE;
3817
3818         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3819         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3820
3821         if (GTK_IS_LABEL (focused_widget)) {
3822                 gchar *selection;
3823                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3824                 gtk_clipboard_set_text (clipboard, selection, -1);
3825                 g_free (selection);
3826                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3827                 gtk_clipboard_store (clipboard);
3828         } else if (GTK_IS_EDITABLE (focused_widget)) {
3829                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3830                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3831                 gtk_clipboard_store (clipboard);
3832         } else if (GTK_IS_HTML (focused_widget)) {
3833                 gtk_html_copy (GTK_HTML (focused_widget));
3834                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3835                 gtk_clipboard_store (clipboard);
3836         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3837                 GtkTextBuffer *buffer;
3838                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3839                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3840                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3841                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3842                         gtk_clipboard_store (clipboard);
3843                 }
3844         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3845                 TnyList *header_list = modest_header_view_get_selected_headers (
3846                                 MODEST_HEADER_VIEW (focused_widget));
3847                 gboolean continue_download = FALSE;
3848                 gint num_of_unc_msgs;
3849
3850                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3851
3852                 if (num_of_unc_msgs) {
3853                         TnyAccount *account = get_account_from_header_list (header_list);
3854                         if (account) {
3855                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3856                                 g_object_unref (account);
3857                         }
3858                 }
3859
3860                 if (num_of_unc_msgs == 0 || continue_download) {
3861                         modest_platform_information_banner (
3862                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3863                         modest_header_view_copy_selection (
3864                                         MODEST_HEADER_VIEW (focused_widget));
3865                 } else
3866                         copied = FALSE;
3867
3868                 g_object_unref (header_list);
3869
3870         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3871                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3872         }
3873
3874         /* Show information banner if there was a copy to clipboard */
3875         if(copied)
3876                 modest_platform_information_banner (
3877                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3878 }
3879
3880 void
3881 modest_ui_actions_on_undo (GtkAction *action,
3882                            ModestWindow *window)
3883 {
3884         ModestEmailClipboard *clipboard = NULL;
3885
3886         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3887                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3888         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3889                 /* Clear clipboard source */
3890                 clipboard = modest_runtime_get_email_clipboard ();
3891                 modest_email_clipboard_clear (clipboard);               
3892         }
3893         else {
3894                 g_return_if_reached ();
3895         }
3896 }
3897
3898 void
3899 modest_ui_actions_on_redo (GtkAction *action,
3900                            ModestWindow *window)
3901 {
3902         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3903                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3904         }
3905         else {
3906                 g_return_if_reached ();
3907         }
3908 }
3909
3910
3911 static void
3912 destroy_information_note (ModestMailOperation *mail_op, 
3913                           gpointer user_data)
3914 {
3915         /* destroy information note */
3916         gtk_widget_destroy (GTK_WIDGET(user_data));
3917 }
3918
3919 static void
3920 destroy_folder_information_note (ModestMailOperation *mail_op, 
3921                                  TnyFolder *new_folder,
3922                                  gpointer user_data)
3923 {
3924         /* destroy information note */
3925         gtk_widget_destroy (GTK_WIDGET(user_data));
3926 }
3927
3928
3929 static void
3930 paste_as_attachment_free (gpointer data)
3931 {
3932         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3933
3934         if (helper->banner) {
3935                 gtk_widget_destroy (helper->banner);
3936                 g_object_unref (helper->banner);
3937         }
3938         g_free (helper);
3939 }
3940
3941 static void
3942 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3943                             TnyHeader *header,
3944                             TnyMsg *msg,
3945                             gpointer userdata)
3946 {
3947         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3948         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3949
3950         if (msg == NULL)
3951                 return;
3952
3953         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3954         
3955 }
3956
3957 void
3958 modest_ui_actions_on_paste (GtkAction *action,
3959                             ModestWindow *window)
3960 {
3961         GtkWidget *focused_widget = NULL;
3962         GtkWidget *inf_note = NULL;
3963         ModestMailOperation *mail_op = NULL;
3964
3965         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3966         if (GTK_IS_EDITABLE (focused_widget)) {
3967                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3968         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3969                 ModestEmailClipboard *e_clipboard = NULL;
3970                 e_clipboard = modest_runtime_get_email_clipboard ();
3971                 if (modest_email_clipboard_cleared (e_clipboard)) {
3972                         GtkTextBuffer *buffer;
3973                         GtkClipboard *clipboard;
3974
3975                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3976                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3977                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3978                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3979                         ModestMailOperation *mail_op;
3980                         TnyFolder *src_folder;
3981                         TnyList *data;
3982                         gboolean delete;
3983                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3984                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3985                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3986                                                                            _CS("ckct_nw_pasting"));
3987                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3988                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3989                         if (helper->banner != NULL) {
3990                                 g_object_ref (G_OBJECT (helper->banner));
3991                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3992                         }
3993
3994                         if (data != NULL) {
3995                                 modest_mail_operation_get_msgs_full (mail_op, 
3996                                                                      data,
3997                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3998                                                                      helper,
3999                                                                      paste_as_attachment_free);
4000                         }
4001                 }
4002         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4003                 ModestEmailClipboard *clipboard = NULL;
4004                 TnyFolder *src_folder = NULL;
4005                 TnyFolderStore *folder_store = NULL;
4006                 TnyList *data = NULL;           
4007                 gboolean delete = FALSE;
4008                 
4009                 /* Check clipboard source */
4010                 clipboard = modest_runtime_get_email_clipboard ();
4011                 if (modest_email_clipboard_cleared (clipboard)) 
4012                         return;
4013                 
4014                 /* Get elements to paste */
4015                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4016
4017                 /* Create a new mail operation */
4018                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4019                 
4020                 /* Get destination folder */
4021                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4022
4023                 /* transfer messages  */
4024                 if (data != NULL) {
4025                         gint response = 0;
4026
4027                         /* Ask for user confirmation */
4028                         response = 
4029                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4030                                                                              TNY_FOLDER (folder_store), 
4031                                                                              delete,
4032                                                                              data);
4033                         
4034                         if (response == GTK_RESPONSE_OK) {
4035                                 /* Launch notification */
4036                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4037                                                                              _CS("ckct_nw_pasting"));
4038                                 if (inf_note != NULL)  {
4039                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4040                                         gtk_widget_show (GTK_WIDGET(inf_note));
4041                                 }
4042
4043                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4044                                 modest_mail_operation_xfer_msgs (mail_op, 
4045                                                                  data,
4046                                                                  TNY_FOLDER (folder_store),
4047                                                                  delete,
4048                                                                  destroy_information_note,
4049                                                                  inf_note);                             
4050                         } else {
4051                                 g_object_unref (mail_op);
4052                         }
4053                         
4054                 } else if (src_folder != NULL) {                        
4055                         /* Launch notification */
4056                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4057                                                                      _CS("ckct_nw_pasting"));
4058                         if (inf_note != NULL)  {
4059                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4060                                 gtk_widget_show (GTK_WIDGET(inf_note));
4061                         }
4062                         
4063                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4064                         modest_mail_operation_xfer_folder (mail_op, 
4065                                                            src_folder,
4066                                                            folder_store,
4067                                                            delete,
4068                                                            destroy_folder_information_note,
4069                                                            inf_note);
4070                 }
4071
4072                 /* Free */
4073                 if (data != NULL) 
4074                         g_object_unref (data);
4075                 if (src_folder != NULL) 
4076                         g_object_unref (src_folder);
4077                 if (folder_store != NULL) 
4078                         g_object_unref (folder_store);
4079         }
4080 }
4081
4082
4083 void
4084 modest_ui_actions_on_select_all (GtkAction *action,
4085                                  ModestWindow *window)
4086 {
4087         GtkWidget *focused_widget;
4088
4089         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4090         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4091                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4092         } else if (GTK_IS_LABEL (focused_widget)) {
4093                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4094         } else if (GTK_IS_EDITABLE (focused_widget)) {
4095                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4096         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4097                 GtkTextBuffer *buffer;
4098                 GtkTextIter start, end;
4099
4100                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4101                 gtk_text_buffer_get_start_iter (buffer, &start);
4102                 gtk_text_buffer_get_end_iter (buffer, &end);
4103                 gtk_text_buffer_select_range (buffer, &start, &end);
4104         } else if (GTK_IS_HTML (focused_widget)) {
4105                 gtk_html_select_all (GTK_HTML (focused_widget));
4106         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4107                 GtkWidget *header_view = focused_widget;
4108                 GtkTreeSelection *selection = NULL;
4109                 
4110                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4111                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4112                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4113                 }
4114                                 
4115                 /* Disable window dimming management */
4116                 modest_window_disable_dimming (MODEST_WINDOW(window));
4117                 
4118                 /* Select all messages */
4119                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4120                 gtk_tree_selection_select_all (selection);
4121
4122                 /* Set focuse on header view */
4123                 gtk_widget_grab_focus (header_view);
4124
4125                 /* Enable window dimming management */
4126                 modest_window_enable_dimming (MODEST_WINDOW(window));
4127                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4128                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4129         }
4130
4131 }
4132
4133 void
4134 modest_ui_actions_on_mark_as_read (GtkAction *action,
4135                                    ModestWindow *window)
4136 {       
4137         g_return_if_fail (MODEST_IS_WINDOW(window));
4138                 
4139         /* Mark each header as read */
4140         do_headers_action (window, headers_action_mark_as_read, NULL);
4141 }
4142
4143 void
4144 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4145                                      ModestWindow *window)
4146 {       
4147         g_return_if_fail (MODEST_IS_WINDOW(window));
4148                 
4149         /* Mark each header as read */
4150         do_headers_action (window, headers_action_mark_as_unread, NULL);
4151 }
4152
4153 void
4154 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4155                                   GtkRadioAction *selected,
4156                                   ModestWindow *window)
4157 {
4158         gint value;
4159
4160         value = gtk_radio_action_get_current_value (selected);
4161         if (MODEST_IS_WINDOW (window)) {
4162                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4163         }
4164 }
4165
4166 void
4167 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4168                                                GtkRadioAction *selected,
4169                                                ModestWindow *window)
4170 {
4171         TnyHeaderFlags flags;
4172         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4173
4174         flags = gtk_radio_action_get_current_value (selected);
4175         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4176 }
4177
4178 void
4179 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4180                                                   GtkRadioAction *selected,
4181                                                   ModestWindow *window)
4182 {
4183         gint file_format;
4184
4185         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4186
4187         file_format = gtk_radio_action_get_current_value (selected);
4188         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4189 }
4190
4191
4192 void
4193 modest_ui_actions_on_zoom_plus (GtkAction *action,
4194                                 ModestWindow *window)
4195 {
4196         g_return_if_fail (MODEST_IS_WINDOW (window));
4197
4198         modest_window_zoom_plus (MODEST_WINDOW (window));
4199 }
4200
4201 void     
4202 modest_ui_actions_on_zoom_minus (GtkAction *action,
4203                                  ModestWindow *window)
4204 {
4205         g_return_if_fail (MODEST_IS_WINDOW (window));
4206
4207         modest_window_zoom_minus (MODEST_WINDOW (window));
4208 }
4209
4210 void     
4211 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4212                                            ModestWindow *window)
4213 {
4214         ModestWindowMgr *mgr;
4215         gboolean fullscreen, active;
4216         g_return_if_fail (MODEST_IS_WINDOW (window));
4217
4218         mgr = modest_runtime_get_window_mgr ();
4219
4220         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4221         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4222
4223         if (active != fullscreen) {
4224                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4225                 gtk_window_present (GTK_WINDOW (window));
4226         }
4227 }
4228
4229 void
4230 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4231                                         ModestWindow *window)
4232 {
4233         ModestWindowMgr *mgr;
4234         gboolean fullscreen;
4235
4236         g_return_if_fail (MODEST_IS_WINDOW (window));
4237
4238         mgr = modest_runtime_get_window_mgr ();
4239         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4240         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4241
4242         gtk_window_present (GTK_WINDOW (window));
4243 }
4244
4245 /* 
4246  * Used by modest_ui_actions_on_details to call do_headers_action 
4247  */
4248 static void
4249 headers_action_show_details (TnyHeader *header, 
4250                              ModestWindow *window,
4251                              gpointer user_data)
4252
4253 {
4254         GtkWidget *dialog;
4255         
4256         /* Create dialog */
4257         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4258
4259         /* Run dialog */
4260         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4261         gtk_widget_show_all (dialog);
4262         gtk_dialog_run (GTK_DIALOG (dialog));
4263
4264         gtk_widget_destroy (dialog);
4265 }
4266
4267 /*
4268  * Show the folder details in a ModestDetailsDialog widget
4269  */
4270 static void
4271 show_folder_details (TnyFolder *folder, 
4272                      GtkWindow *window)
4273 {
4274         GtkWidget *dialog;
4275         
4276         /* Create dialog */
4277         dialog = modest_details_dialog_new_with_folder (window, folder);
4278
4279         /* Run dialog */
4280         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4281         gtk_widget_show_all (dialog);
4282         gtk_dialog_run (GTK_DIALOG (dialog));
4283
4284         gtk_widget_destroy (dialog);
4285 }
4286
4287 /*
4288  * Show the header details in a ModestDetailsDialog widget
4289  */
4290 void     
4291 modest_ui_actions_on_details (GtkAction *action, 
4292                               ModestWindow *win)
4293 {
4294         TnyList * headers_list;
4295         TnyIterator *iter;
4296         TnyHeader *header;              
4297
4298         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4299                 TnyMsg *msg;
4300
4301                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4302                 if (!msg)
4303                         return;
4304                 g_object_unref (msg);           
4305
4306                 headers_list = get_selected_headers (win);
4307                 if (!headers_list)
4308                         return;
4309
4310                 iter = tny_list_create_iterator (headers_list);
4311
4312                 header = TNY_HEADER (tny_iterator_get_current (iter));
4313                 if (header) {
4314                         headers_action_show_details (header, win, NULL);
4315                         g_object_unref (header);
4316                 }
4317
4318                 g_object_unref (iter);
4319                 g_object_unref (headers_list);
4320
4321         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4322                 GtkWidget *folder_view, *header_view;
4323
4324                 /* Check which widget has the focus */
4325                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4326                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4327                 if (gtk_widget_is_focus (folder_view)) {
4328                         TnyFolderStore *folder_store
4329                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4330                         if (!folder_store) {
4331                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4332                                 return; 
4333                         }
4334                         /* Show only when it's a folder */
4335                         /* This function should not be called for account items, 
4336                          * because we dim the menu item for them. */
4337                         if (TNY_IS_FOLDER (folder_store)) {
4338                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4339                         }
4340
4341                         g_object_unref (folder_store);
4342
4343                 } else {
4344                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4345                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4346                         /* Show details of each header */
4347                         do_headers_action (win, headers_action_show_details, header_view);
4348                 }
4349         }
4350 }
4351
4352 void     
4353 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4354                                      ModestMsgEditWindow *window)
4355 {
4356         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4357
4358         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4359 }
4360
4361 void     
4362 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4363                                       ModestMsgEditWindow *window)
4364 {
4365         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4366
4367         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4368 }
4369
4370 void
4371 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4372                                        ModestMainWindow *main_window)
4373 {
4374         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4375
4376         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4377                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4378         else
4379                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4380 }
4381
4382 void 
4383 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4384                                      ModestWindow *window)
4385 {
4386         gboolean active, fullscreen = FALSE;
4387         ModestWindowMgr *mgr;
4388
4389         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4390
4391         /* Check if we want to toggle the toolbar vuew in fullscreen
4392            or normal mode */
4393         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4394                      "ViewShowToolbarFullScreen")) {
4395                 fullscreen = TRUE;
4396         }
4397
4398         /* Toggle toolbar */
4399         mgr = modest_runtime_get_window_mgr ();
4400         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4401 }
4402
4403 void     
4404 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4405                                            ModestMsgEditWindow *window)
4406 {
4407         modest_msg_edit_window_select_font (window);
4408 }
4409
4410
4411 void
4412 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4413                                                   const gchar *display_name,
4414                                                   GtkWindow *window)
4415 {
4416         /* don't update the display name if it was already set;
4417          * updating the display name apparently is expensive */
4418         const gchar* old_name = gtk_window_get_title (window);
4419
4420         if (display_name == NULL)
4421                 display_name = " ";
4422
4423         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4424                 return; /* don't do anything */
4425
4426         /* This is usually used to change the title of the main window, which
4427          * is the one that holds the folder view. Note that this change can
4428          * happen even when the widget doesn't have the focus. */
4429         gtk_window_set_title (window, display_name);
4430
4431 }
4432
4433 void
4434 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4435 {
4436         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4437         modest_msg_edit_window_select_contacts (window);
4438 }
4439
4440 void
4441 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4442 {
4443         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4444         modest_msg_edit_window_check_names (window, FALSE);
4445 }
4446
4447 static void
4448 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4449 {
4450         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4451                                          GTK_WIDGET (user_data));
4452 }
4453
4454 /*
4455  * This function is used to track changes in the selection of the
4456  * folder view that is inside the "move to" dialog to enable/disable
4457  * the OK button because we do not want the user to select a disallowed
4458  * destination for a folder.
4459  * The user also not desired to be able to use NEW button on items where
4460  * folder creation is not possibel.
4461  */
4462 static void
4463 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4464                                             TnyFolderStore *folder_store,
4465                                             gboolean selected,
4466                                             gpointer user_data)
4467 {
4468         GtkWidget *dialog = NULL;
4469         GtkWidget *ok_button = NULL, *new_button = NULL;
4470         GList *children = NULL;
4471         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4472         gboolean moving_folder = FALSE;
4473         gboolean is_local_account = TRUE;
4474         GtkWidget *folder_view = NULL;
4475         ModestTnyFolderRules rules;
4476
4477         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4478         
4479         if (!selected)
4480                 return;
4481         
4482         /* Get the OK button */
4483         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4484         if (!dialog)
4485                 return;
4486
4487         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4488 #ifdef MODEST_PLATFORM_MAEMO
4489         ok_button = GTK_WIDGET (children->next->next->data);
4490         new_button = GTK_WIDGET (children->next->data);
4491 #else
4492         ok_button = GTK_WIDGET (children->data);
4493         new_button = GTK_WIDGET (children->next->next->data);
4494 #endif
4495         g_list_free (children);
4496
4497         /* check if folder_store is an remote account */
4498         if (TNY_IS_ACCOUNT (folder_store)) {
4499                 TnyAccount *local_account = NULL;
4500                 TnyAccount *mmc_account = NULL;
4501                 ModestTnyAccountStore *account_store = NULL;
4502
4503                 account_store = modest_runtime_get_account_store ();
4504                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4505                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4506
4507                 if ((gpointer) local_account != (gpointer) folder_store &&
4508                     (gpointer) mmc_account != (gpointer) folder_store) {
4509                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4510                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4511                         if (proto_name != NULL) {
4512                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4513                         }
4514                         is_local_account = FALSE;
4515                         /* New button should be dimmed on remote
4516                            POP account root */
4517                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4518                 }
4519                 g_object_unref (local_account);
4520                 g_object_unref (mmc_account);
4521         }
4522
4523         /* Check the target folder rules */
4524         if (TNY_IS_FOLDER (folder_store)) {
4525                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4526                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4527                         ok_sensitive = FALSE;
4528                         new_sensitive = FALSE;
4529                         goto end;
4530                 }
4531         }
4532
4533         /* Check if we're moving a folder */
4534         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4535                 /* Get the widgets */
4536                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4537                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4538                 if (gtk_widget_is_focus (folder_view))
4539                         moving_folder = TRUE;
4540         }
4541
4542         if (moving_folder) {
4543                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4544
4545                 /* Get the folder to move */
4546                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4547                 
4548                 /* Check that we're not moving to the same folder */
4549                 if (TNY_IS_FOLDER (moved_folder)) {
4550                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4551                         if (parent == folder_store)
4552                                 ok_sensitive = FALSE;
4553                         g_object_unref (parent);
4554                 } 
4555
4556                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4557                         /* Do not allow to move to an account unless it's the
4558                            local folders account */
4559                         if (!is_local_account)
4560                                 ok_sensitive = FALSE;
4561                 } 
4562
4563                 if (ok_sensitive && (moved_folder == folder_store)) {
4564                         /* Do not allow to move to itself */
4565                         ok_sensitive = FALSE;
4566                 }
4567                 g_object_unref (moved_folder);
4568         } else {
4569                 TnyFolder *src_folder = NULL;
4570
4571                 /* Moving a message */
4572                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4573
4574                         TnyHeader *header = NULL;
4575                         header = modest_msg_view_window_get_header
4576                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4577                         if (!TNY_IS_HEADER(header))
4578                                 g_warning ("%s: could not get source header", __FUNCTION__);
4579                         else
4580                                 src_folder = tny_header_get_folder (header);
4581
4582                         if (header)
4583                                 g_object_unref (header);
4584                 } else {
4585                         src_folder = 
4586                                 TNY_FOLDER (modest_folder_view_get_selected
4587                                             (MODEST_FOLDER_VIEW (folder_view)));
4588                 }
4589
4590                 if (TNY_IS_FOLDER(src_folder)) {
4591                         /* Do not allow to move the msg to the same folder */
4592                         /* Do not allow to move the msg to an account */
4593                         if ((gpointer) src_folder == (gpointer) folder_store ||
4594                             TNY_IS_ACCOUNT (folder_store))
4595                                 ok_sensitive = FALSE;
4596                         g_object_unref (src_folder);
4597                 } else
4598                         g_warning ("%s: could not get source folder", __FUNCTION__);
4599         }
4600
4601  end:
4602         /* Set sensitivity of the OK button */
4603         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4604         /* Set sensitivity of the NEW button */
4605         gtk_widget_set_sensitive (new_button, new_sensitive);
4606 }
4607
4608
4609 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4610
4611 static GtkWidget*
4612 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4613 {
4614         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4615                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4616 }
4617
4618 static GtkWidget*
4619 create_move_to_dialog (GtkWindow *win,
4620                        GtkWidget *folder_view,
4621                        GtkWidget **tree_view)
4622 {
4623         GtkWidget *dialog, *scroll;
4624         GtkWidget *new_button;
4625
4626         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4627                                               GTK_WINDOW (win),
4628                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4629                                               NULL);
4630
4631 #ifdef MODEST_PLATFORM_MAEMO
4632         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4633         /* We do this manually so GTK+ does not associate a response ID for
4634          * the button. */
4635         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4636         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4637         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4638 #else
4639         /* We do this manually so GTK+ does not associate a response ID for
4640          * the button. */
4641         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4642         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4643         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4644         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4645         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4646         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4647         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4648 #endif
4649
4650         /* Create scrolled window */
4651         scroll = gtk_scrolled_window_new (NULL, NULL);
4652         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4653                                          GTK_POLICY_AUTOMATIC,
4654                                          GTK_POLICY_AUTOMATIC);
4655
4656 #ifndef MODEST_PLATFORM_MAEMO
4657         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4658 #endif
4659
4660         /* Create folder view */
4661         *tree_view = modest_platform_create_folder_view (NULL);
4662
4663         /* Track changes in the selection to
4664          * disable the OK button whenever "Move to" is not possible
4665          * disbale NEW button whenever New is not possible */
4666         g_signal_connect (*tree_view,
4667                           "folder_selection_changed",
4668                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4669                           win);
4670
4671         /* Listen to clicks on New button */
4672         g_signal_connect (G_OBJECT (new_button), 
4673                           "clicked", 
4674                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4675                           *tree_view);
4676
4677         /* It could happen that we're trying to move a message from a
4678            window (msg window for example) after the main window was
4679            closed, so we can not just get the model of the folder
4680            view */
4681         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4682                 const gchar *visible_id = NULL;
4683
4684                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4685                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4686                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4687                                                MODEST_FOLDER_VIEW(*tree_view));
4688
4689                 visible_id = 
4690                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4691
4692                 /* Show the same account than the one that is shown in the main window */
4693                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4694                                                                              visible_id);
4695         } else {
4696                 const gchar *active_account_name = NULL;
4697                 ModestAccountMgr *mgr = NULL;
4698                 ModestAccountSettings *settings = NULL;
4699                 ModestServerAccountSettings *store_settings = NULL;
4700
4701                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4702                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4703                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4704                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4705
4706                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4707                 mgr = modest_runtime_get_account_mgr ();
4708                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4709
4710                 if (settings) {
4711                         const gchar *store_account_name;
4712                         store_settings = modest_account_settings_get_store_settings (settings);
4713                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4714
4715                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4716                                                                                      store_account_name);
4717                         g_object_unref (store_settings);
4718                         g_object_unref (settings);
4719                 }
4720         }
4721
4722         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4723          *   get_folder_view_from_move_to_dialog 
4724          * (see above) later (needed for focus handling) 
4725          */
4726         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4727
4728         
4729         /* Hide special folders */
4730         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4731
4732         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4733
4734         /* Add scroll to dialog */
4735         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4736                             scroll, TRUE, TRUE, 0);
4737
4738         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4739 #ifdef MODEST_PLATFORM_MAEMO
4740         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4741 #else
4742         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4743 #endif
4744
4745         return dialog;
4746 }
4747
4748
4749
4750 /*
4751  * Shows a confirmation dialog to the user when we're moving messages
4752  * from a remote server to the local storage. Returns the dialog
4753  * response. If it's other kind of movement then it always returns
4754  * GTK_RESPONSE_OK
4755  *
4756  * This one is used by the next functions:
4757  *      modest_ui_actions_on_paste                      - commented out
4758  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4759  */
4760 gint
4761 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4762                                              TnyFolder *dest_folder,
4763                                              gboolean delete,
4764                                              TnyList *headers)
4765 {
4766         gint response = GTK_RESPONSE_OK;
4767         TnyAccount *account = NULL;
4768         TnyFolder *src_folder = NULL;
4769         TnyIterator *iter = NULL;
4770         TnyHeader *header = NULL;
4771
4772         /* return with OK if the destination is a remote folder */
4773         if (modest_tny_folder_is_remote_folder (dest_folder))
4774                 return GTK_RESPONSE_OK;
4775
4776         /* Get source folder */
4777         iter = tny_list_create_iterator (headers);
4778         header = TNY_HEADER (tny_iterator_get_current (iter));
4779         if (header) {
4780                 src_folder = tny_header_get_folder (header);
4781                 g_object_unref (header);
4782         }
4783         g_object_unref (iter);
4784
4785         /* if no src_folder, message may be an attahcment */
4786         if (src_folder == NULL) 
4787                 return GTK_RESPONSE_CANCEL;
4788
4789         /* If the source is a local or MMC folder */
4790         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4791                 g_object_unref (src_folder);
4792                 return GTK_RESPONSE_OK;
4793         }
4794
4795         /* Get the account */
4796         account = tny_folder_get_account (src_folder);
4797
4798         /* now if offline we ask the user */
4799         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4800                 response = GTK_RESPONSE_OK;
4801         else
4802                 response = GTK_RESPONSE_CANCEL;
4803
4804         /* Frees */
4805         g_object_unref (src_folder);
4806         g_object_unref (account);
4807
4808         return response;
4809 }
4810
4811 static void
4812 move_to_helper_destroyer (gpointer user_data)
4813 {
4814         MoveToHelper *helper = (MoveToHelper *) user_data;
4815
4816         /* Close the "Pasting" information banner */
4817         if (helper->banner) {
4818                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4819                 g_object_unref (helper->banner);
4820         }
4821         if (helper->reference != NULL)
4822                 gtk_tree_row_reference_free (helper->reference);
4823         g_free (helper);
4824 }
4825
4826 static void
4827 move_to_cb (ModestMailOperation *mail_op, 
4828             gpointer user_data)
4829 {
4830         MoveToHelper *helper = (MoveToHelper *) user_data;
4831
4832         /* Note that the operation could have failed, in that case do
4833            nothing */
4834         if (modest_mail_operation_get_status (mail_op) == 
4835             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4836
4837                 GObject *object = modest_mail_operation_get_source (mail_op);
4838                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4839                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4840
4841                         if (!modest_msg_view_window_select_next_message (self) &&
4842                             !modest_msg_view_window_select_previous_message (self)) {
4843                                 /* No more messages to view, so close this window */
4844                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4845                         }
4846                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4847                         GtkWidget *header_view;
4848                         GtkTreePath *path;
4849                         GtkTreeSelection *sel;
4850
4851                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4852                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4853                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4854                         path = gtk_tree_row_reference_get_path (helper->reference);
4855                         /* We need to unselect the previous one
4856                            because we could be copying instead of
4857                            moving */
4858                         gtk_tree_selection_unselect_all (sel);
4859                         gtk_tree_selection_select_path (sel, path);
4860                         gtk_tree_path_free (path);
4861                 }
4862                 g_object_unref (object);
4863         }
4864         /* Destroy the helper */
4865         move_to_helper_destroyer (helper);
4866 }
4867
4868 static void
4869 folder_move_to_cb (ModestMailOperation *mail_op, 
4870                    TnyFolder *new_folder,
4871                    gpointer user_data)
4872 {
4873         GtkWidget *folder_view;
4874         GObject *object;
4875
4876         object = modest_mail_operation_get_source (mail_op);
4877         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4878                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4879         g_object_ref (folder_view);
4880         g_object_unref (object);
4881         move_to_cb (mail_op, user_data);
4882         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4883         g_object_unref (folder_view);
4884 }
4885
4886 static void
4887 msgs_move_to_cb (ModestMailOperation *mail_op, 
4888                  gpointer user_data)
4889 {
4890         move_to_cb (mail_op, user_data);
4891 }
4892
4893 void
4894 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4895                                              gpointer user_data)
4896 {
4897         ModestWindow *main_window = NULL;
4898         
4899         /* Disable next automatic folder selection */
4900         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4901                                                          FALSE); /* don't create */
4902         if (main_window) {
4903                 GObject *win = NULL;
4904                 GtkWidget *folder_view = NULL;
4905         
4906                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4907                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4908                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4909                 
4910                 if (user_data && TNY_IS_FOLDER (user_data)) {
4911                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4912                                                           TNY_FOLDER (user_data), FALSE);
4913                 }
4914
4915                 /* Show notification dialog only if the main window exists */
4916                 win = modest_mail_operation_get_source (mail_op);
4917                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4918                                                         _("mail_in_ui_folder_move_target_error"), 
4919                                                         FALSE);
4920                 if (win)
4921                         g_object_unref (win);
4922         }
4923 }
4924
4925 static void
4926 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4927                        TnyHeader *header, 
4928                        gboolean canceled,
4929                        TnyMsg *msg, 
4930                        GError *err,
4931                        gpointer user_data)
4932 {
4933         TnyList *parts;
4934         TnyIterator *iter;
4935         gint pending_purges = 0;
4936         gboolean some_purged = FALSE;
4937         ModestWindow *win = MODEST_WINDOW (user_data);
4938         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4939
4940         /* If there was any error */
4941         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4942                 modest_window_mgr_unregister_header (mgr, header);
4943                 return;
4944         }
4945
4946         /* Once the message has been retrieved for purging, we check if
4947          * it's all ok for purging */
4948
4949         parts = tny_simple_list_new ();
4950         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4951         iter = tny_list_create_iterator (parts);
4952
4953         while (!tny_iterator_is_done (iter)) {
4954                 TnyMimePart *part;
4955                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4956                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4957                         if (tny_mime_part_is_purged (part))
4958                                 some_purged = TRUE;
4959                         else
4960                                 pending_purges++;
4961                 }
4962
4963                 if (part)
4964                         g_object_unref (part);
4965
4966                 tny_iterator_next (iter);
4967         }
4968         g_object_unref (iter);
4969         
4970
4971         if (pending_purges>0) {
4972                 gint response;
4973                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4974
4975                 if (response == GTK_RESPONSE_OK) {
4976                         GtkWidget *info;
4977                         info =
4978                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
4979                         iter = tny_list_create_iterator (parts);
4980                         while (!tny_iterator_is_done (iter)) {
4981                                 TnyMimePart *part;
4982                                 
4983                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4984                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4985                                         tny_mime_part_set_purged (part);
4986
4987                                 if (part)
4988                                         g_object_unref (part);
4989
4990                                 tny_iterator_next (iter);
4991                         }
4992                         g_object_unref (iter);
4993                         
4994                         tny_msg_rewrite_cache (msg);
4995
4996                         gtk_widget_destroy (info);
4997                 }
4998         }
4999
5000         modest_window_mgr_unregister_header (mgr, header);
5001
5002         g_object_unref (parts);
5003 }
5004
5005 static void
5006 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5007                                                      ModestMainWindow *win)
5008 {
5009         GtkWidget *header_view;
5010         TnyList *header_list;
5011         TnyHeader *header;
5012         TnyHeaderFlags flags;
5013         ModestWindow *msg_view_window =  NULL;
5014         gboolean found;
5015
5016         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5017
5018         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5019                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5020
5021         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5022         if (!header_list) {
5023                 g_warning ("%s: no header selected", __FUNCTION__);
5024                 return;
5025         }
5026         
5027         if (tny_list_get_length (header_list) == 1) {
5028                 TnyIterator *iter = tny_list_create_iterator (header_list);
5029                 header = TNY_HEADER (tny_iterator_get_current (iter));
5030                 g_object_unref (iter);
5031         } else
5032                 return;
5033         
5034         if (!header || !TNY_IS_HEADER(header)) {
5035                 g_warning ("%s: header is not valid", __FUNCTION__);
5036                 return;
5037         }
5038         
5039         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5040                                                           header, &msg_view_window);
5041         flags = tny_header_get_flags (header);
5042         if (!(flags & TNY_HEADER_FLAG_CACHED))
5043                 return;
5044         if (found) {
5045                 if (msg_view_window != NULL) 
5046                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5047                 else {
5048                         /* do nothing; uid was registered before, so window is probably on it's way */
5049                         g_warning ("debug: header %p has already been registered", header);
5050                 }
5051         } else {
5052                 ModestMailOperation *mail_op = NULL;
5053                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5054                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5055                                                                          modest_ui_actions_disk_operations_error_handler,
5056                                                                          NULL, NULL);
5057                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5058                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5059                 
5060                 g_object_unref (mail_op);
5061         }
5062         if (header)
5063                 g_object_unref (header);
5064         if (header_list)
5065                 g_object_unref (header_list);
5066 }
5067
5068 /*
5069  * Checks if we need a connection to do the transfer and if the user
5070  * wants to connect to complete it
5071  */
5072 void
5073 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5074                                        TnyFolderStore *src_folder,
5075                                        TnyList *headers,
5076                                        TnyFolder *dst_folder,
5077                                        gboolean delete_originals,
5078                                        gboolean *need_connection,
5079                                        gboolean *do_xfer)
5080 {
5081         TnyAccount *src_account;
5082         gint uncached_msgs = 0;
5083
5084         uncached_msgs = header_list_count_uncached_msgs (headers);
5085
5086         /* We don't need any further check if
5087          *
5088          * 1- the source folder is local OR
5089          * 2- the device is already online
5090          */
5091         if (!modest_tny_folder_store_is_remote (src_folder) ||
5092             tny_device_is_online (modest_runtime_get_device())) {
5093                 *need_connection = FALSE;
5094                 *do_xfer = TRUE;
5095                 return;
5096         }
5097
5098         /* We must ask for a connection when
5099          *
5100          *   - the message(s) is not already cached   OR 
5101          *   - the message(s) is cached but the leave_on_server setting
5102          * is FALSE (because we need to sync the source folder to
5103          * delete the message from the server (for IMAP we could do it
5104          * offline, it'll take place the next time we get a
5105          * connection)
5106          */
5107         src_account = get_account_from_folder_store (src_folder);
5108         if (uncached_msgs > 0) {
5109                 guint num_headers;
5110                 const gchar *msg;
5111
5112                 *need_connection = TRUE;
5113                 num_headers = tny_list_get_length (headers);
5114                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5115
5116                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5117                     GTK_RESPONSE_CANCEL) {
5118                         *do_xfer = FALSE;
5119                 } else {
5120                         *do_xfer = TRUE;
5121                 }
5122         } else {
5123                 /* The transfer is possible and the user wants to */
5124                 *do_xfer = TRUE;
5125
5126                 if (remote_folder_is_pop (src_folder) && delete_originals) {
5127                         const gchar *account_name;
5128                         gboolean leave_on_server;
5129                         
5130                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5131                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5132                                                                                   account_name);
5133                         
5134                         if (leave_on_server == TRUE) {
5135                                 *need_connection = FALSE;
5136                         } else {
5137                                 *need_connection = TRUE;
5138                         }
5139                 } else {
5140                         *need_connection = FALSE;
5141                 }
5142         }
5143
5144         /* Frees */
5145         g_object_unref (src_account);
5146 }
5147
5148 static void
5149 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5150                              gpointer user_data)
5151 {
5152         ModestWindow *main_window = NULL;
5153
5154         /* Disable next automatic folder selection */
5155         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5156                                                          FALSE); /* don't create */
5157         if (main_window) {
5158                 GObject *win = modest_mail_operation_get_source (mail_op);
5159                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5160                                                         _("mail_in_ui_folder_move_target_error"), 
5161                                                         FALSE);
5162                 if (win)
5163                         g_object_unref (win);
5164         }
5165         move_to_helper_destroyer (user_data);
5166 }
5167
5168 typedef struct {
5169         TnyFolderStore *dst_folder;
5170         TnyList *headers;
5171 } XferMsgsHelper;
5172
5173 /**
5174  * Utility function that transfer messages from both the main window
5175  * and the msg view window when using the "Move to" dialog
5176  */
5177 static void
5178 xfer_messages_performer  (gboolean canceled, 
5179                           GError *err,
5180                           GtkWindow *parent_window, 
5181                           TnyAccount *account, 
5182                           gpointer user_data)
5183 {
5184         ModestWindow *win = MODEST_WINDOW (parent_window);
5185         TnyAccount *dst_account = NULL;
5186         const gchar *proto_str = NULL;
5187         gboolean dst_is_pop = FALSE;
5188         XferMsgsHelper *helper;
5189         MoveToHelper *movehelper;
5190         ModestMailOperation *mail_op;
5191
5192         helper = (XferMsgsHelper *) user_data;
5193
5194         if (canceled || err) {
5195                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5196                         /* Show the proper error message */
5197                         modest_ui_actions_on_account_connection_error (parent_window, account);
5198                 }
5199                 goto end;
5200         }
5201
5202         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5203         proto_str = tny_account_get_proto (dst_account);
5204
5205         /* tinymail will return NULL for local folders it seems */
5206         dst_is_pop = proto_str &&
5207                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
5208                  MODEST_PROTOCOL_STORE_POP);
5209
5210         g_object_unref (dst_account);
5211
5212         if (dst_is_pop) {
5213                 modest_platform_information_banner (GTK_WIDGET (win),
5214                                                     NULL,
5215                                                     ngettext("mail_in_ui_folder_move_target_error",
5216                                                              "mail_in_ui_folder_move_targets_error",
5217                                                              tny_list_get_length (helper->headers)));
5218                 goto end;
5219         }
5220
5221         movehelper = g_new0 (MoveToHelper, 1);
5222         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5223                                                                _CS("ckct_nw_pasting"));
5224         if (movehelper->banner != NULL)  {
5225                 g_object_ref (movehelper->banner);
5226                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5227         }
5228
5229         if (MODEST_IS_MAIN_WINDOW (win)) {
5230                 GtkWidget *header_view = 
5231                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5232                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5233                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5234         }
5235
5236         /* Perform the mail operation */
5237         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5238                                                                  xfer_messages_error_handler,
5239                                                                  movehelper, NULL);
5240         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5241                                          mail_op);
5242
5243         modest_mail_operation_xfer_msgs (mail_op, 
5244                                          helper->headers,
5245                                          TNY_FOLDER (helper->dst_folder),
5246                                          TRUE,
5247                                          msgs_move_to_cb,
5248                                          movehelper);
5249
5250         g_object_unref (G_OBJECT (mail_op));
5251  end:
5252         g_object_unref (helper->dst_folder);
5253         g_object_unref (helper->headers);
5254         g_slice_free (XferMsgsHelper, helper);
5255 }
5256
5257 typedef struct {
5258         TnyFolder *src_folder;
5259         TnyFolderStore *dst_folder;
5260         gboolean delete_original;
5261         GtkWidget *folder_view;
5262 } MoveFolderInfo;
5263
5264 static void
5265 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5266                 TnyAccount *account, gpointer user_data)
5267 {
5268         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5269         GtkTreeSelection *sel;
5270         ModestMailOperation *mail_op = NULL;
5271         
5272         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5273                 g_object_unref (G_OBJECT (info->src_folder));
5274                 g_object_unref (G_OBJECT (info->dst_folder));
5275                 g_free (info);
5276                 return;
5277         }
5278         
5279         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5280         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5281                         _CS("ckct_nw_pasting"));
5282         if (helper->banner != NULL)  {
5283                 g_object_ref (helper->banner);
5284                 gtk_widget_show (GTK_WIDGET(helper->banner));
5285         }
5286         /* Clean folder on header view before moving it */
5287         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5288         gtk_tree_selection_unselect_all (sel);
5289
5290         /* Let gtk events run. We need that the folder
5291            view frees its reference to the source
5292            folder *before* issuing the mail operation
5293            so we need the signal handler of selection
5294            changed to happen before the mail
5295            operation 
5296         while (gtk_events_pending ())
5297                 gtk_main_iteration ();   */
5298
5299         mail_op =
5300                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5301                                 modest_ui_actions_move_folder_error_handler,
5302                                 info->src_folder, NULL);
5303         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5304                         mail_op);
5305
5306         /* Select *after* the changes */
5307         /* TODO: this function hangs UI after transfer */ 
5308         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5309         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5310
5311         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5312                                           TNY_FOLDER (info->dst_folder), TRUE);
5313         modest_mail_operation_xfer_folder (mail_op,
5314                         TNY_FOLDER (info->src_folder),
5315                         info->dst_folder,
5316                         info->delete_original, 
5317                         folder_move_to_cb, 
5318                         helper);
5319         g_object_unref (G_OBJECT (info->src_folder));
5320
5321         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5322         /* } */
5323         
5324         /* Unref mail operation */
5325         g_object_unref (G_OBJECT (mail_op));
5326         g_object_unref (G_OBJECT (info->dst_folder));
5327         g_free (user_data);
5328 }
5329
5330 static TnyAccount *
5331 get_account_from_folder_store (TnyFolderStore *folder_store) 
5332 {
5333         if (TNY_IS_ACCOUNT (folder_store))
5334                 return g_object_ref (folder_store);
5335         else
5336                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5337 }
5338
5339 /*
5340  * UI handler for the "Move to" action when invoked from the
5341  * ModestMainWindow
5342  */
5343 static void 
5344 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5345                                           GtkWidget *folder_view,
5346                                           TnyFolderStore *dst_folder,
5347                                           ModestMainWindow *win)
5348 {
5349         ModestHeaderView *header_view = NULL;
5350         TnyFolderStore *src_folder = NULL;
5351
5352         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5353
5354         /* Get the source folder */
5355         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5356
5357         /* Get header view */
5358         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5359
5360         /* Get folder or messages to transfer */
5361         if (gtk_widget_is_focus (folder_view)) {
5362                 gboolean do_xfer = TRUE;
5363
5364                 /* Allow only to transfer folders to the local root folder */
5365                 if (TNY_IS_ACCOUNT (dst_folder) && 
5366                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5367                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5368                         do_xfer = FALSE;
5369                 } else if (!TNY_IS_FOLDER (src_folder)) {
5370                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5371                         do_xfer = FALSE;
5372                 }
5373
5374                 if (do_xfer) {                  
5375                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5376                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5377
5378                         info->src_folder = g_object_ref (src_folder);
5379                         info->dst_folder = g_object_ref (dst_folder);
5380                         info->delete_original = TRUE;
5381                         info->folder_view = folder_view;
5382
5383                         connect_info->callback = on_move_folder_cb;
5384                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5385                         connect_info->data = info;
5386
5387                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5388                                                                    TNY_FOLDER_STORE (src_folder), 
5389                                                                    connect_info);
5390                 }
5391         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5392                 TnyList *headers;
5393
5394                 headers = modest_header_view_get_selected_headers(header_view);
5395
5396                 /* Transfer the messages */
5397                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5398                                                             headers, TNY_FOLDER (dst_folder));
5399
5400                 g_object_unref (headers);
5401         }
5402
5403         /* Frees */
5404         g_object_unref (src_folder);
5405 }
5406
5407
5408 void
5409 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5410                                             TnyFolder *src_folder,
5411                                             TnyList *headers,
5412                                             TnyFolder *dst_folder)
5413 {
5414         gboolean need_connection = TRUE;
5415         gboolean do_xfer = TRUE;
5416         XferMsgsHelper *helper;
5417         
5418         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5419                                                headers, TNY_FOLDER (dst_folder),
5420                                                TRUE, &need_connection, 
5421                                                &do_xfer);
5422
5423         /* If we don't want to transfer just return */
5424         if (!do_xfer)
5425                 return;
5426
5427         /* Create the helper */
5428         helper = g_slice_new (XferMsgsHelper);
5429         helper->dst_folder = g_object_ref (dst_folder);
5430         helper->headers = g_object_ref (headers);
5431
5432         if (need_connection) {
5433                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5434                 connect_info->callback = xfer_messages_performer;
5435                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5436                 connect_info->data = helper;
5437                 
5438                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5439                                                            TNY_FOLDER_STORE (src_folder), 
5440                                                            connect_info);
5441         } else {
5442                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5443                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5444                                          src_account, helper);
5445                 g_object_unref (src_account);
5446         }
5447 }
5448
5449 /*
5450  * UI handler for the "Move to" action when invoked from the
5451  * ModestMsgViewWindow
5452  */
5453 static void 
5454 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5455                                               TnyFolderStore *dst_folder,
5456                                               ModestMsgViewWindow *win)
5457 {
5458         TnyList *headers = NULL;
5459         TnyHeader *header = NULL;
5460         TnyFolder *src_folder = NULL;
5461
5462         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5463
5464         /* Create header list */
5465         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5466         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5467         headers = tny_simple_list_new ();
5468         tny_list_append (headers, G_OBJECT (header));
5469
5470         /* Transfer the messages */
5471         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5472                                                     TNY_FOLDER (dst_folder));
5473
5474         /* Frees */
5475         g_object_unref (header);
5476         g_object_unref (headers);
5477 }
5478
5479 void 
5480 modest_ui_actions_on_move_to (GtkAction *action, 
5481                               ModestWindow *win)
5482 {
5483         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5484         gint result = 0;
5485         TnyFolderStore *dst_folder = NULL;
5486         ModestMainWindow *main_window;
5487
5488         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5489                           MODEST_IS_MSG_VIEW_WINDOW (win));
5490
5491         /* Get the main window if exists */
5492         if (MODEST_IS_MAIN_WINDOW (win))
5493                 main_window = MODEST_MAIN_WINDOW (win);
5494         else
5495                 main_window = 
5496                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5497                                                                                FALSE)); /* don't create */
5498
5499         /* Get the folder view widget if exists */
5500         if (main_window)
5501                 folder_view = modest_main_window_get_child_widget (main_window,
5502                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5503         else
5504                 folder_view = NULL;
5505
5506         /* Create and run the dialog */
5507         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5508         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5509         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5510         result = gtk_dialog_run (GTK_DIALOG(dialog));
5511         g_object_ref (tree_view);
5512         gtk_widget_destroy (dialog);
5513
5514         if (result != GTK_RESPONSE_ACCEPT)
5515                 return;
5516
5517         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5518         /* Do window specific stuff */
5519         if (MODEST_IS_MAIN_WINDOW (win)) {
5520                 modest_ui_actions_on_main_window_move_to (action,
5521                                 folder_view,
5522                                 dst_folder,
5523                                 MODEST_MAIN_WINDOW (win));
5524         } else {
5525                 modest_ui_actions_on_msg_view_window_move_to (action,
5526                                 dst_folder,
5527                                 MODEST_MSG_VIEW_WINDOW (win));
5528         }
5529
5530         if (dst_folder)
5531                 g_object_unref (dst_folder);
5532 }
5533
5534 /*
5535  * Calls #HeadersFunc for each header already selected in the main
5536  * window or the message currently being shown in the msg view window
5537  */
5538 static void
5539 do_headers_action (ModestWindow *win, 
5540                    HeadersFunc func,
5541                    gpointer user_data)
5542 {
5543         TnyList *headers_list = NULL;
5544         TnyIterator *iter = NULL;
5545         TnyHeader *header = NULL;
5546         TnyFolder *folder = NULL;
5547
5548         /* Get headers */
5549         headers_list = get_selected_headers (win);
5550         if (!headers_list)
5551                 return;
5552
5553         /* Get the folder */
5554         iter = tny_list_create_iterator (headers_list);
5555         header = TNY_HEADER (tny_iterator_get_current (iter));
5556         if (header) {
5557                 folder = tny_header_get_folder (header);
5558                 g_object_unref (header);
5559         }
5560
5561         /* Call the function for each header */
5562         while (!tny_iterator_is_done (iter)) {
5563                 header = TNY_HEADER (tny_iterator_get_current (iter));
5564                 func (header, win, user_data);
5565                 g_object_unref (header);
5566                 tny_iterator_next (iter);
5567         }
5568
5569         /* Trick: do a poke status in order to speed up the signaling
5570            of observers */
5571         tny_folder_poke_status (folder);
5572
5573         /* Frees */
5574         g_object_unref (folder);
5575         g_object_unref (iter);
5576         g_object_unref (headers_list);
5577 }
5578
5579 void 
5580 modest_ui_actions_view_attachment (GtkAction *action,
5581                                    ModestWindow *window)
5582 {
5583         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5584                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5585         } else {
5586                 /* not supported window for this action */
5587                 g_return_if_reached ();
5588         }
5589 }
5590
5591 void
5592 modest_ui_actions_save_attachments (GtkAction *action,
5593                                     ModestWindow *window)
5594 {
5595         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5596
5597                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5598                         return;
5599
5600                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5601         } else {
5602                 /* not supported window for this action */
5603                 g_return_if_reached ();
5604         }
5605 }
5606
5607 void
5608 modest_ui_actions_remove_attachments (GtkAction *action,
5609                                       ModestWindow *window)
5610 {
5611         if (MODEST_IS_MAIN_WINDOW (window)) {
5612                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5613         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5614                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5615         } else {
5616                 /* not supported window for this action */
5617                 g_return_if_reached ();
5618         }
5619 }
5620
5621 void 
5622 modest_ui_actions_on_settings (GtkAction *action, 
5623                                ModestWindow *win)
5624 {
5625         GtkWidget *dialog;
5626
5627         dialog = modest_platform_get_global_settings_dialog ();
5628         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5629         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5630         gtk_widget_show_all (dialog);
5631
5632         gtk_dialog_run (GTK_DIALOG (dialog));
5633
5634         gtk_widget_destroy (dialog);
5635 }
5636
5637 void 
5638 modest_ui_actions_on_help (GtkAction *action, 
5639                            GtkWindow *win)
5640 {
5641         const gchar *help_id;
5642
5643         g_return_if_fail (win && GTK_IS_WINDOW(win));
5644         
5645         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5646
5647         if (help_id)
5648                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5649 }
5650
5651 void 
5652 modest_ui_actions_on_csm_help (GtkAction *action, 
5653                                GtkWindow *win)
5654 {
5655         const gchar* help_id = NULL;
5656         GtkWidget *folder_view;
5657         TnyFolderStore *folder_store;
5658
5659         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5660
5661         /* Get selected folder */
5662         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5663                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5664         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5665
5666         /* Switch help_id */
5667         if (folder_store && TNY_IS_FOLDER (folder_store))
5668                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5669
5670         if (folder_store)
5671                 g_object_unref (folder_store);
5672
5673         if (help_id)
5674                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5675         else
5676                 modest_ui_actions_on_help (action, win);
5677 }
5678
5679 static void     
5680 retrieve_contents_cb (ModestMailOperation *mail_op, 
5681                       TnyHeader *header, 
5682                       gboolean canceled,
5683                       TnyMsg *msg,
5684                       GError *err,
5685                       gpointer user_data)
5686 {
5687         /* We only need this callback to show an error in case of
5688            memory low condition */
5689         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5690 }
5691
5692 static void
5693 retrieve_msg_contents_performer (gboolean canceled, 
5694                                  GError *err,
5695                                  GtkWindow *parent_window, 
5696                                  TnyAccount *account, 
5697                                  gpointer user_data)
5698 {
5699         ModestMailOperation *mail_op;
5700         TnyList *headers = TNY_LIST (user_data);
5701
5702         if (err || canceled) {
5703                 check_memory_full_error ((GtkWidget *) parent_window, err);
5704                 goto out;
5705         }
5706
5707         /* Create mail operation */
5708         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5709                                                                  modest_ui_actions_disk_operations_error_handler, 
5710                                                                  NULL, NULL);
5711         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5712         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5713
5714         /* Frees */
5715         g_object_unref (mail_op);
5716  out:
5717         g_object_unref (headers);
5718         g_object_unref (account);
5719 }
5720
5721 void 
5722 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5723                                             ModestWindow *window)
5724 {
5725         TnyList *headers = NULL;
5726         TnyAccount *account = NULL;
5727         TnyIterator *iter = NULL;
5728         TnyHeader *header = NULL;
5729         TnyFolder *folder = NULL;
5730
5731         /* Get headers */
5732         headers = get_selected_headers (window);
5733         if (!headers)
5734                 return;
5735
5736         /* Pick the account */
5737         iter = tny_list_create_iterator (headers);
5738         header = TNY_HEADER (tny_iterator_get_current (iter));
5739         folder = tny_header_get_folder (header);
5740         account = tny_folder_get_account (folder);
5741         g_object_unref (folder);
5742         g_object_unref (header);
5743         g_object_unref (iter);
5744
5745         /* Connect and perform the message retrieval */
5746         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5747                                              g_object_ref (account), 
5748                                              retrieve_msg_contents_performer, 
5749                                              g_object_ref (headers));
5750
5751         /* Frees */
5752         g_object_unref (account);
5753         g_object_unref (headers);
5754 }
5755
5756 void
5757 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5758 {
5759         g_return_if_fail (MODEST_IS_WINDOW (window));
5760
5761         /* Update dimmed */
5762         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5763 }
5764
5765 void
5766 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5767 {
5768         g_return_if_fail (MODEST_IS_WINDOW (window));
5769
5770         /* Update dimmed */
5771         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5772 }
5773
5774 void
5775 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5776                                           ModestWindow *window)
5777 {
5778         g_return_if_fail (MODEST_IS_WINDOW (window));
5779         
5780         /* Update dimmed */
5781         modest_ui_actions_check_menu_dimming_rules (window);
5782 }
5783
5784 void
5785 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5786                                           ModestWindow *window)
5787 {
5788         g_return_if_fail (MODEST_IS_WINDOW (window));
5789
5790         /* Update dimmed */
5791         modest_ui_actions_check_menu_dimming_rules (window);
5792 }
5793
5794 void
5795 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5796                                           ModestWindow *window)
5797 {
5798         g_return_if_fail (MODEST_IS_WINDOW (window));
5799
5800         /* Update dimmed */
5801         modest_ui_actions_check_menu_dimming_rules (window);
5802 }
5803
5804 void
5805 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5806                                             ModestWindow *window)
5807 {
5808         g_return_if_fail (MODEST_IS_WINDOW (window));
5809
5810         /* Update dimmed */
5811         modest_ui_actions_check_menu_dimming_rules (window);
5812 }
5813
5814 void
5815 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5816                                           ModestWindow *window)
5817 {
5818         g_return_if_fail (MODEST_IS_WINDOW (window));
5819
5820         /* Update dimmed */
5821         modest_ui_actions_check_menu_dimming_rules (window);
5822 }
5823
5824 void
5825 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5826                                           ModestWindow *window)
5827 {
5828         g_return_if_fail (MODEST_IS_WINDOW (window));
5829
5830         /* Update dimmed */
5831         modest_ui_actions_check_menu_dimming_rules (window);
5832 }
5833
5834 void
5835 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5836                                                  ModestWindow *window)
5837 {
5838         g_return_if_fail (MODEST_IS_WINDOW (window));
5839
5840         /* Update dimmed */
5841         modest_ui_actions_check_menu_dimming_rules (window);
5842 }
5843
5844 void
5845 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5846                                                      ModestWindow *window)
5847 {
5848         g_return_if_fail (MODEST_IS_WINDOW (window));
5849
5850         /* Update dimmed */
5851         modest_ui_actions_check_menu_dimming_rules (window);
5852 }
5853
5854 void
5855 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5856                                                      ModestWindow *window)
5857 {
5858         g_return_if_fail (MODEST_IS_WINDOW (window));
5859
5860         /* Update dimmed */
5861         modest_ui_actions_check_menu_dimming_rules (window);
5862 }
5863
5864 void
5865 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5866 {
5867         g_return_if_fail (MODEST_IS_WINDOW (window));
5868
5869         /* we check for low-mem; in that case, show a warning, and don't allow
5870          * searching
5871          */
5872         if (modest_platform_check_memory_low (window, TRUE))
5873                 return;
5874         
5875         modest_platform_show_search_messages (GTK_WINDOW (window));
5876 }
5877
5878 void     
5879 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5880 {
5881         g_return_if_fail (MODEST_IS_WINDOW (win));
5882
5883
5884         /* we check for low-mem; in that case, show a warning, and don't allow
5885          * for the addressbook
5886          */
5887         if (modest_platform_check_memory_low (win, TRUE))
5888                 return;
5889
5890
5891         modest_platform_show_addressbook (GTK_WINDOW (win));
5892 }
5893
5894
5895 void
5896 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5897                                           ModestWindow *window)
5898 {
5899         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5900
5901         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5902 }
5903
5904 static void 
5905 on_send_receive_finished (ModestMailOperation  *mail_op, 
5906                            gpointer user_data)
5907 {
5908         GtkWidget *header_view, *folder_view;
5909         TnyFolderStore *folder_store;
5910         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5911
5912         /* Set send/receive operation finished */       
5913         modest_main_window_notify_send_receive_completed (main_win);
5914
5915         /* Don't refresh the current folder if there were any errors */
5916         if (modest_mail_operation_get_status (mail_op) !=
5917             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5918                 return;
5919         
5920         /* Refresh the current folder if we're viewing a window. We do
5921            this because the user won't be able to see the new mails in
5922            the selected folder after a Send&Receive because it only
5923            performs a poke_status, i.e, only the number of read/unread
5924            messages is updated, but the new headers are not
5925            downloaded */
5926         folder_view = modest_main_window_get_child_widget (main_win, 
5927                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5928         if (!folder_view)
5929                 return;
5930
5931         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5932         
5933         /* Do not need to refresh INBOX again because the
5934            update_account does it always automatically */
5935         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5936             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5937                 ModestMailOperation *refresh_op;
5938
5939                 header_view = modest_main_window_get_child_widget (main_win,
5940                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5941                 
5942                 /* We do not need to set the contents style
5943                    because it hasn't changed. We also do not
5944                    need to save the widget status. Just force
5945                    a refresh */
5946                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5947                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5948                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5949                                                       folder_refreshed_cb, main_win);
5950                 g_object_unref (refresh_op);
5951         }
5952         
5953         if (folder_store)
5954                 g_object_unref (folder_store);
5955 }
5956
5957
5958 void 
5959 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5960                                                 TnyHeader *header, 
5961                                                 TnyMsg *msg, 
5962                                                 GError *err, 
5963                                                 gpointer user_data)
5964 {
5965         const gchar* server_name = NULL;
5966         TnyTransportAccount *server_account;
5967         gchar *message = NULL;
5968
5969         /* Don't show anything if the user cancelled something or the
5970          * send receive request is not interactive. Authentication
5971          * errors are managed by the account store so no need to show
5972          * a dialog here again */
5973         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5974             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
5975             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5976                 return;
5977
5978
5979         /* Get the server name: */
5980         server_account = 
5981                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5982         if (server_account)
5983                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
5984         else
5985                 g_return_if_reached ();
5986
5987         /* Show the appropriate message text for the GError: */
5988         switch (err->code) {
5989         case TNY_SERVICE_ERROR_CONNECT:
5990                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5991                 break;
5992         case TNY_SERVICE_ERROR_SEND:
5993                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5994                 break;
5995         case TNY_SERVICE_ERROR_UNAVAILABLE:
5996                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5997                 break;
5998         default:
5999                 g_warning ("%s: unexpected ERROR %d",
6000                            __FUNCTION__, err->code);
6001                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6002                 break;  
6003         }
6004
6005         modest_platform_run_information_dialog (NULL, message, FALSE);
6006         g_free (message);
6007         g_object_unref (server_account);
6008 }
6009
6010 void
6011 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6012                                                 gchar *msg_id, 
6013                                                 guint status,
6014                                                 gpointer user_data)
6015 {
6016         ModestMainWindow *main_window = NULL;
6017         ModestWindowMgr *mgr = NULL;
6018         GtkWidget *folder_view = NULL, *header_view = NULL;
6019         TnyFolderStore *selected_folder = NULL;
6020         TnyFolderType folder_type;
6021
6022         mgr = modest_runtime_get_window_mgr ();
6023         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6024                                                                              FALSE));/* don't create */
6025         if (!main_window)
6026                 return;
6027
6028         /* Check if selected folder is OUTBOX */
6029         folder_view = modest_main_window_get_child_widget (main_window,
6030                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6031         header_view = modest_main_window_get_child_widget (main_window,
6032                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6033
6034         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6035         if (!TNY_IS_FOLDER (selected_folder)) 
6036                 goto frees;
6037
6038         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6039 #if GTK_CHECK_VERSION(2, 8, 0) 
6040         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6041         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6042                 GtkTreeViewColumn *tree_column;
6043
6044                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6045                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6046                 gtk_tree_view_column_queue_resize (tree_column);
6047         }
6048 #else
6049         gtk_widget_queue_draw (header_view);
6050 #endif          
6051
6052         /* Rerun dimming rules, because the message could become deletable for example */
6053         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6054                                                  MODEST_DIMMING_RULES_TOOLBAR);
6055         
6056         /* Free */
6057  frees:
6058         if (selected_folder != NULL)
6059                 g_object_unref (selected_folder);
6060 }
6061
6062 void 
6063 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6064                                                TnyAccount *account)
6065 {
6066         ModestTransportStoreProtocol proto;
6067         const gchar *proto_name;
6068         gchar *error_note = NULL;
6069         
6070         proto_name = tny_account_get_proto (account);
6071         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
6072         
6073         switch (proto) {
6074         case MODEST_PROTOCOL_STORE_POP:
6075                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
6076                                               tny_account_get_hostname (account));
6077                 break;
6078         case MODEST_PROTOCOL_STORE_IMAP:
6079                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
6080                                               tny_account_get_hostname (account));
6081                 break;
6082         case MODEST_PROTOCOL_STORE_MAILDIR:
6083         case MODEST_PROTOCOL_STORE_MBOX:
6084                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
6085                 break;
6086         default:
6087                 g_warning ("%s: This should not be reached", __FUNCTION__);
6088         }
6089
6090         if (error_note) {
6091                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6092                 g_free (error_note);
6093         }
6094 }
6095
6096 gchar *
6097 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6098 {
6099         gchar *msg = NULL;
6100         TnyFolderStore *folder = NULL;
6101         TnyAccount *account = NULL;
6102         ModestTransportStoreProtocol proto;
6103         TnyHeader *header = NULL;
6104
6105         if (MODEST_IS_MAIN_WINDOW (win)) {
6106                 GtkWidget *header_view;
6107                 TnyList* headers = NULL;
6108                 TnyIterator *iter;
6109                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6110                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6111                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6112                 if (!headers || tny_list_get_length (headers) == 0) {
6113                         if (headers)
6114                                 g_object_unref (headers);
6115                         return NULL;
6116                 }
6117                 iter = tny_list_create_iterator (headers);
6118                 header = TNY_HEADER (tny_iterator_get_current (iter));
6119                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6120                 g_object_unref (iter);
6121                 g_object_unref (headers);
6122         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6123                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6124                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6125         }
6126
6127         /* Get the account type */
6128         account = tny_folder_get_account (TNY_FOLDER (folder));
6129         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
6130         if (proto == MODEST_PROTOCOL_STORE_POP) {
6131                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
6132         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
6133                 gchar *subject;
6134                 subject = tny_header_dup_subject (header);
6135                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
6136                                        subject);
6137                 g_free (subject);
6138         } else {
6139                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6140         }
6141
6142         /* Frees */
6143         g_object_unref (account);
6144         g_object_unref (folder);
6145         g_object_unref (header);
6146
6147         return msg;
6148 }