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