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