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