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