ec46c8386289f8b8e09da278de6dd44364d39553
[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         /* It could happen that we're trying to move a message from a
4787            window (msg window for example) after the main window was
4788            closed, so we can not just get the model of the folder
4789            view */
4790         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4791                 const gchar *visible_id = NULL;
4792
4793                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4794                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4795                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4796                                                MODEST_FOLDER_VIEW(*tree_view));
4797
4798                 visible_id = 
4799                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4800
4801                 /* Show the same account than the one that is shown in the main window */
4802                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4803                                                                              visible_id);
4804         } else {
4805                 const gchar *active_account_name = NULL;
4806                 ModestAccountMgr *mgr = NULL;
4807                 ModestAccountSettings *settings = NULL;
4808                 ModestServerAccountSettings *store_settings = NULL;
4809
4810                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4811                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4812                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4813                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4814
4815                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4816                 mgr = modest_runtime_get_account_mgr ();
4817                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4818
4819                 if (settings) {
4820                         const gchar *store_account_name;
4821                         store_settings = modest_account_settings_get_store_settings (settings);
4822                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4823
4824                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4825                                                                                      store_account_name);
4826                         g_object_unref (store_settings);
4827                         g_object_unref (settings);
4828                 }
4829         }
4830
4831         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4832          *   get_folder_view_from_move_to_dialog 
4833          * (see above) later (needed for focus handling) 
4834          */
4835         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4836
4837         
4838         /* Hide special folders */
4839         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4840
4841 #ifdef MODEST_TOOLKIT_HILDON2
4842         gtk_container_add (GTK_CONTAINER (pannable), *tree_view);
4843         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4844                             pannable, TRUE, TRUE, 0);
4845 #else
4846         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4847         /* Add scroll to dialog */
4848         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4849                             scroll, TRUE, TRUE, 0);
4850 #endif
4851
4852
4853         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4854 #ifndef MODEST_TOOLKIT_GTK
4855         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4856 #else
4857         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4858 #endif
4859
4860         return dialog;
4861 }
4862
4863
4864
4865 /*
4866  * Shows a confirmation dialog to the user when we're moving messages
4867  * from a remote server to the local storage. Returns the dialog
4868  * response. If it's other kind of movement then it always returns
4869  * GTK_RESPONSE_OK
4870  *
4871  * This one is used by the next functions:
4872  *      modest_ui_actions_on_paste                      - commented out
4873  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4874  */
4875 gint
4876 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4877                                              TnyFolder *dest_folder,
4878                                              gboolean delete,
4879                                              TnyList *headers)
4880 {
4881         gint response = GTK_RESPONSE_OK;
4882         TnyAccount *account = NULL;
4883         TnyFolder *src_folder = NULL;
4884         TnyIterator *iter = NULL;
4885         TnyHeader *header = NULL;
4886
4887         /* return with OK if the destination is a remote folder */
4888         if (modest_tny_folder_is_remote_folder (dest_folder))
4889                 return GTK_RESPONSE_OK;
4890
4891         /* Get source folder */
4892         iter = tny_list_create_iterator (headers);
4893         header = TNY_HEADER (tny_iterator_get_current (iter));
4894         if (header) {
4895                 src_folder = tny_header_get_folder (header);
4896                 g_object_unref (header);
4897         }
4898         g_object_unref (iter);
4899
4900         /* if no src_folder, message may be an attahcment */
4901         if (src_folder == NULL) 
4902                 return GTK_RESPONSE_CANCEL;
4903
4904         /* If the source is a local or MMC folder */
4905         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4906                 g_object_unref (src_folder);
4907                 return GTK_RESPONSE_OK;
4908         }
4909
4910         /* Get the account */
4911         account = tny_folder_get_account (src_folder);
4912
4913         /* now if offline we ask the user */
4914         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4915                 response = GTK_RESPONSE_OK;
4916         else
4917                 response = GTK_RESPONSE_CANCEL;
4918
4919         /* Frees */
4920         g_object_unref (src_folder);
4921         g_object_unref (account);
4922
4923         return response;
4924 }
4925
4926 static void
4927 move_to_helper_destroyer (gpointer user_data)
4928 {
4929         MoveToHelper *helper = (MoveToHelper *) user_data;
4930
4931         /* Close the "Pasting" information banner */
4932         if (helper->banner) {
4933                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4934                 g_object_unref (helper->banner);
4935         }
4936         if (gtk_tree_row_reference_valid (helper->reference)) {
4937                 gtk_tree_row_reference_free (helper->reference);
4938                 helper->reference = NULL;
4939         }
4940         g_free (helper);
4941 }
4942
4943 static void
4944 move_to_cb (ModestMailOperation *mail_op, 
4945             gpointer user_data)
4946 {
4947         MoveToHelper *helper = (MoveToHelper *) user_data;
4948
4949         /* Note that the operation could have failed, in that case do
4950            nothing */
4951         if (modest_mail_operation_get_status (mail_op) == 
4952             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4953
4954                 GObject *object = modest_mail_operation_get_source (mail_op);
4955                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4956                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4957
4958                         if (!modest_msg_view_window_select_next_message (self) &&
4959                             !modest_msg_view_window_select_previous_message (self)) {
4960                                 /* No more messages to view, so close this window */
4961                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4962                         }
4963                 } else if (MODEST_IS_MAIN_WINDOW (object) && 
4964                            gtk_tree_row_reference_valid (helper->reference)) {
4965                         GtkWidget *header_view;
4966                         GtkTreePath *path;
4967                         GtkTreeSelection *sel;
4968
4969                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4970                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4971                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4972                         path = gtk_tree_row_reference_get_path (helper->reference);
4973                         /* We need to unselect the previous one
4974                            because we could be copying instead of
4975                            moving */
4976                         gtk_tree_selection_unselect_all (sel);
4977                         gtk_tree_selection_select_path (sel, path);
4978                         gtk_tree_path_free (path);
4979                 }
4980                 g_object_unref (object);
4981         }
4982         /* Destroy the helper */
4983         move_to_helper_destroyer (helper);
4984 }
4985
4986 static void
4987 folder_move_to_cb (ModestMailOperation *mail_op, 
4988                    TnyFolder *new_folder,
4989                    gpointer user_data)
4990 {
4991         GtkWidget *folder_view;
4992         GObject *object;
4993
4994         object = modest_mail_operation_get_source (mail_op);
4995         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4996                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4997         g_object_ref (folder_view);
4998         g_object_unref (object);
4999         move_to_cb (mail_op, user_data);
5000         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5001         g_object_unref (folder_view);
5002 }
5003
5004 static void
5005 msgs_move_to_cb (ModestMailOperation *mail_op, 
5006                  gpointer user_data)
5007 {
5008         move_to_cb (mail_op, user_data);
5009 }
5010
5011 void
5012 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
5013                                              gpointer user_data)
5014 {
5015         ModestWindow *main_window = NULL;
5016         
5017         /* Disable next automatic folder selection */
5018         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5019                                                          FALSE); /* don't create */
5020         if (main_window) {
5021                 GObject *win = NULL;
5022                 GtkWidget *folder_view = NULL;
5023         
5024                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5025                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
5026                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5027                 
5028                 if (user_data && TNY_IS_FOLDER (user_data)) {
5029                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
5030                                                           TNY_FOLDER (user_data), FALSE);
5031                 }
5032
5033                 /* Show notification dialog only if the main window exists */
5034                 win = modest_mail_operation_get_source (mail_op);
5035                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5036                                                         _("mail_in_ui_folder_move_target_error"), 
5037                                                         FALSE);
5038                 if (win)
5039                         g_object_unref (win);
5040         }
5041 }
5042
5043 static void
5044 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
5045                        TnyHeader *header, 
5046                        gboolean canceled,
5047                        TnyMsg *msg, 
5048                        GError *err,
5049                        gpointer user_data)
5050 {
5051         TnyList *parts;
5052         TnyIterator *iter;
5053         gint pending_purges = 0;
5054         gboolean some_purged = FALSE;
5055         ModestWindow *win = MODEST_WINDOW (user_data);
5056         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5057
5058         /* If there was any error */
5059         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5060                 modest_window_mgr_unregister_header (mgr, header);
5061                 return;
5062         }
5063
5064         /* Once the message has been retrieved for purging, we check if
5065          * it's all ok for purging */
5066
5067         parts = tny_simple_list_new ();
5068         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5069         iter = tny_list_create_iterator (parts);
5070
5071         while (!tny_iterator_is_done (iter)) {
5072                 TnyMimePart *part;
5073                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5074                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5075                         if (tny_mime_part_is_purged (part))
5076                                 some_purged = TRUE;
5077                         else
5078                                 pending_purges++;
5079                 }
5080
5081                 if (part)
5082                         g_object_unref (part);
5083
5084                 tny_iterator_next (iter);
5085         }
5086         g_object_unref (iter);
5087         
5088
5089         if (pending_purges>0) {
5090                 gint response;
5091                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5092
5093                 if (response == GTK_RESPONSE_OK) {
5094                         GtkWidget *info;
5095                         info =
5096                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5097                         iter = tny_list_create_iterator (parts);
5098                         while (!tny_iterator_is_done (iter)) {
5099                                 TnyMimePart *part;
5100                                 
5101                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5102                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5103                                         tny_mime_part_set_purged (part);
5104
5105                                 if (part)
5106                                         g_object_unref (part);
5107
5108                                 tny_iterator_next (iter);
5109                         }
5110                         g_object_unref (iter);
5111                         
5112                         tny_msg_rewrite_cache (msg);
5113
5114                         gtk_widget_destroy (info);
5115                 }
5116         }
5117
5118         modest_window_mgr_unregister_header (mgr, header);
5119
5120         g_object_unref (parts);
5121 }
5122
5123 static void
5124 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5125                                                      ModestMainWindow *win)
5126 {
5127         GtkWidget *header_view;
5128         TnyList *header_list;
5129         TnyHeader *header;
5130         TnyHeaderFlags flags;
5131         ModestWindow *msg_view_window =  NULL;
5132         gboolean found;
5133
5134         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5135
5136         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5137                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5138
5139         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5140         if (!header_list) {
5141                 g_warning ("%s: no header selected", __FUNCTION__);
5142                 return;
5143         }
5144         
5145         if (tny_list_get_length (header_list) == 1) {
5146                 TnyIterator *iter = tny_list_create_iterator (header_list);
5147                 header = TNY_HEADER (tny_iterator_get_current (iter));
5148                 g_object_unref (iter);
5149         } else
5150                 return;
5151         
5152         if (!header || !TNY_IS_HEADER(header)) {
5153                 g_warning ("%s: header is not valid", __FUNCTION__);
5154                 return;
5155         }
5156         
5157         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5158                                                           header, &msg_view_window);
5159         flags = tny_header_get_flags (header);
5160         if (!(flags & TNY_HEADER_FLAG_CACHED))
5161                 return;
5162         if (found) {
5163                 if (msg_view_window != NULL) 
5164                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5165                 else {
5166                         /* do nothing; uid was registered before, so window is probably on it's way */
5167                         g_warning ("debug: header %p has already been registered", header);
5168                 }
5169         } else {
5170                 ModestMailOperation *mail_op = NULL;
5171                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5172                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5173                                                                          modest_ui_actions_disk_operations_error_handler,
5174                                                                          NULL, NULL);
5175                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5176                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5177                 
5178                 g_object_unref (mail_op);
5179         }
5180         if (header)
5181                 g_object_unref (header);
5182         if (header_list)
5183                 g_object_unref (header_list);
5184 }
5185
5186 /*
5187  * Checks if we need a connection to do the transfer and if the user
5188  * wants to connect to complete it
5189  */
5190 void
5191 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5192                                        TnyFolderStore *src_folder,
5193                                        TnyList *headers,
5194                                        TnyFolder *dst_folder,
5195                                        gboolean delete_originals,
5196                                        gboolean *need_connection,
5197                                        gboolean *do_xfer)
5198 {
5199         TnyAccount *src_account;
5200         gint uncached_msgs = 0;
5201
5202         uncached_msgs = header_list_count_uncached_msgs (headers);
5203
5204         /* We don't need any further check if
5205          *
5206          * 1- the source folder is local OR
5207          * 2- the device is already online
5208          */
5209         if (!modest_tny_folder_store_is_remote (src_folder) ||
5210             tny_device_is_online (modest_runtime_get_device())) {
5211                 *need_connection = FALSE;
5212                 *do_xfer = TRUE;
5213                 return;
5214         }
5215
5216         /* We must ask for a connection when
5217          *
5218          *   - the message(s) is not already cached   OR 
5219          *   - the message(s) is cached but the leave_on_server setting
5220          * is FALSE (because we need to sync the source folder to
5221          * delete the message from the server (for IMAP we could do it
5222          * offline, it'll take place the next time we get a
5223          * connection)
5224          */
5225         src_account = get_account_from_folder_store (src_folder);
5226         if (uncached_msgs > 0) {
5227                 guint num_headers;
5228                 const gchar *msg;
5229
5230                 *need_connection = TRUE;
5231                 num_headers = tny_list_get_length (headers);
5232                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5233
5234                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5235                     GTK_RESPONSE_CANCEL) {
5236                         *do_xfer = FALSE;
5237                 } else {
5238                         *do_xfer = TRUE;
5239                 }
5240         } else {
5241                 /* The transfer is possible and the user wants to */
5242                 *do_xfer = TRUE;
5243
5244                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5245                         const gchar *account_name;
5246                         gboolean leave_on_server;
5247                         
5248                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5249                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5250                                                                                   account_name);
5251                         
5252                         if (leave_on_server == TRUE) {
5253                                 *need_connection = FALSE;
5254                         } else {
5255                                 *need_connection = TRUE;
5256                         }
5257                 } else {
5258                         *need_connection = FALSE;
5259                 }
5260         }
5261
5262         /* Frees */
5263         g_object_unref (src_account);
5264 }
5265
5266 static void
5267 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5268                              gpointer user_data)
5269 {
5270         ModestWindow *main_window = NULL;
5271
5272         /* Disable next automatic folder selection */
5273         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5274                                                          FALSE); /* don't create */
5275         if (main_window) {
5276                 GObject *win = modest_mail_operation_get_source (mail_op);
5277                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5278                                                         _("mail_in_ui_folder_move_target_error"), 
5279                                                         FALSE);
5280                 if (win)
5281                         g_object_unref (win);
5282         }
5283         move_to_helper_destroyer (user_data);
5284 }
5285
5286 typedef struct {
5287         TnyFolderStore *dst_folder;
5288         TnyList *headers;
5289 } XferMsgsHelper;
5290
5291 /**
5292  * Utility function that transfer messages from both the main window
5293  * and the msg view window when using the "Move to" dialog
5294  */
5295 static void
5296 xfer_messages_performer  (gboolean canceled, 
5297                           GError *err,
5298                           GtkWindow *parent_window, 
5299                           TnyAccount *account, 
5300                           gpointer user_data)
5301 {
5302         ModestWindow *win = MODEST_WINDOW (parent_window);
5303         TnyAccount *dst_account = NULL;
5304         gboolean dst_forbids_message_add = FALSE;
5305         XferMsgsHelper *helper;
5306         MoveToHelper *movehelper;
5307         ModestMailOperation *mail_op;
5308
5309         helper = (XferMsgsHelper *) user_data;
5310
5311         if (canceled || err) {
5312                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5313                         /* Show the proper error message */
5314                         modest_ui_actions_on_account_connection_error (parent_window, account);
5315                 }
5316                 goto end;
5317         }
5318
5319         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5320
5321         /* tinymail will return NULL for local folders it seems */
5322         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5323                                                                                   modest_tny_account_get_protocol_type (dst_account),
5324                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5325         g_object_unref (dst_account);
5326
5327         if (dst_forbids_message_add) {
5328                 modest_platform_information_banner (GTK_WIDGET (win),
5329                                                     NULL,
5330                                                     ngettext("mail_in_ui_folder_move_target_error",
5331                                                              "mail_in_ui_folder_move_targets_error",
5332                                                              tny_list_get_length (helper->headers)));
5333                 goto end;
5334         }
5335
5336         movehelper = g_new0 (MoveToHelper, 1);
5337         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5338                                                                _CS("ckct_nw_pasting"));
5339         if (movehelper->banner != NULL)  {
5340                 g_object_ref (movehelper->banner);
5341                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5342         }
5343
5344         if (MODEST_IS_MAIN_WINDOW (win)) {
5345                 GtkWidget *header_view = 
5346                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5347                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5348                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5349         }
5350
5351         /* Perform the mail operation */
5352         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5353                                                                  xfer_messages_error_handler,
5354                                                                  movehelper, NULL);
5355         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5356                                          mail_op);
5357
5358         modest_mail_operation_xfer_msgs (mail_op, 
5359                                          helper->headers,
5360                                          TNY_FOLDER (helper->dst_folder),
5361                                          TRUE,
5362                                          msgs_move_to_cb,
5363                                          movehelper);
5364
5365         g_object_unref (G_OBJECT (mail_op));
5366  end:
5367         g_object_unref (helper->dst_folder);
5368         g_object_unref (helper->headers);
5369         g_slice_free (XferMsgsHelper, helper);
5370 }
5371
5372 typedef struct {
5373         TnyFolder *src_folder;
5374         TnyFolderStore *dst_folder;
5375         gboolean delete_original;
5376         GtkWidget *folder_view;
5377 } MoveFolderInfo;
5378
5379 static void
5380 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5381                 TnyAccount *account, gpointer user_data)
5382 {
5383         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5384         GtkTreeSelection *sel;
5385         ModestMailOperation *mail_op = NULL;
5386         
5387         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5388                 g_object_unref (G_OBJECT (info->src_folder));
5389                 g_object_unref (G_OBJECT (info->dst_folder));
5390                 g_free (info);
5391                 return;
5392         }
5393         
5394         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5395         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5396                         _CS("ckct_nw_pasting"));
5397         if (helper->banner != NULL)  {
5398                 g_object_ref (helper->banner);
5399                 gtk_widget_show (GTK_WIDGET(helper->banner));
5400         }
5401         /* Clean folder on header view before moving it */
5402         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5403         gtk_tree_selection_unselect_all (sel);
5404
5405         /* Let gtk events run. We need that the folder
5406            view frees its reference to the source
5407            folder *before* issuing the mail operation
5408            so we need the signal handler of selection
5409            changed to happen before the mail
5410            operation 
5411         while (gtk_events_pending ())
5412                 gtk_main_iteration ();   */
5413
5414         mail_op =
5415                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5416                                 modest_ui_actions_move_folder_error_handler,
5417                                 info->src_folder, NULL);
5418         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5419                         mail_op);
5420
5421         /* Select *after* the changes */
5422         /* TODO: this function hangs UI after transfer */ 
5423         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5424         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5425
5426         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5427                                           TNY_FOLDER (info->dst_folder), TRUE);
5428         modest_mail_operation_xfer_folder (mail_op,
5429                         TNY_FOLDER (info->src_folder),
5430                         info->dst_folder,
5431                         info->delete_original, 
5432                         folder_move_to_cb, 
5433                         helper);
5434         g_object_unref (G_OBJECT (info->src_folder));
5435
5436         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5437         /* } */
5438         
5439         /* Unref mail operation */
5440         g_object_unref (G_OBJECT (mail_op));
5441         g_object_unref (G_OBJECT (info->dst_folder));
5442         g_free (user_data);
5443 }
5444
5445 static TnyAccount *
5446 get_account_from_folder_store (TnyFolderStore *folder_store) 
5447 {
5448         if (TNY_IS_ACCOUNT (folder_store))
5449                 return g_object_ref (folder_store);
5450         else
5451                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5452 }
5453
5454 /*
5455  * UI handler for the "Move to" action when invoked from the
5456  * ModestMainWindow
5457  */
5458 static void 
5459 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5460                                           GtkWidget *folder_view,
5461                                           TnyFolderStore *dst_folder,
5462                                           ModestMainWindow *win)
5463 {
5464         ModestHeaderView *header_view = NULL;
5465         TnyFolderStore *src_folder = NULL;
5466
5467         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5468
5469         /* Get the source folder */
5470         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5471
5472         /* Get header view */
5473         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5474
5475         /* Get folder or messages to transfer */
5476         if (gtk_widget_is_focus (folder_view)) {
5477                 gboolean do_xfer = TRUE;
5478
5479                 /* Allow only to transfer folders to the local root folder */
5480                 if (TNY_IS_ACCOUNT (dst_folder) && 
5481                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5482                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5483                         do_xfer = FALSE;
5484                 } else if (!TNY_IS_FOLDER (src_folder)) {
5485                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5486                         do_xfer = FALSE;
5487                 }
5488
5489                 if (do_xfer) {                  
5490                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5491                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5492
5493                         info->src_folder = g_object_ref (src_folder);
5494                         info->dst_folder = g_object_ref (dst_folder);
5495                         info->delete_original = TRUE;
5496                         info->folder_view = folder_view;
5497
5498                         connect_info->callback = on_move_folder_cb;
5499                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5500                         connect_info->data = info;
5501
5502                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5503                                                                    TNY_FOLDER_STORE (src_folder), 
5504                                                                    connect_info);
5505                 }
5506         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5507                 TnyList *headers;
5508
5509                 headers = modest_header_view_get_selected_headers(header_view);
5510
5511                 /* Transfer the messages */
5512                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5513                                                             headers, TNY_FOLDER (dst_folder));
5514
5515                 g_object_unref (headers);
5516         }
5517
5518         /* Frees */
5519         g_object_unref (src_folder);
5520 }
5521
5522
5523 void
5524 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5525                                             TnyFolder *src_folder,
5526                                             TnyList *headers,
5527                                             TnyFolder *dst_folder)
5528 {
5529         gboolean need_connection = TRUE;
5530         gboolean do_xfer = TRUE;
5531         XferMsgsHelper *helper;
5532
5533         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5534         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5535         g_return_if_fail (TNY_IS_LIST (headers));
5536         
5537         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5538                                                headers, TNY_FOLDER (dst_folder),
5539                                                TRUE, &need_connection, 
5540                                                &do_xfer);
5541
5542         /* If we don't want to transfer just return */
5543         if (!do_xfer)
5544                 return;
5545
5546         /* Create the helper */
5547         helper = g_slice_new (XferMsgsHelper);
5548         helper->dst_folder = g_object_ref (dst_folder);
5549         helper->headers = g_object_ref (headers);
5550
5551         if (need_connection) {
5552                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5553                 connect_info->callback = xfer_messages_performer;
5554                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5555                 connect_info->data = helper;
5556                 
5557                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5558                                                            TNY_FOLDER_STORE (src_folder), 
5559                                                            connect_info);
5560         } else {
5561                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5562                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5563                                          src_account, helper);
5564                 g_object_unref (src_account);
5565         }
5566 }
5567
5568 /*
5569  * UI handler for the "Move to" action when invoked from the
5570  * ModestMsgViewWindow
5571  */
5572 static void 
5573 modest_ui_actions_on_window_move_to (GtkAction *action, 
5574                                      TnyFolderStore *dst_folder,
5575                                      ModestWindow *win)
5576 {
5577         TnyList *headers = NULL;
5578         TnyFolder *src_folder = NULL;
5579
5580         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5581
5582         /* Create header list */
5583         headers = get_selected_headers (MODEST_WINDOW (win));
5584
5585         if (tny_list_get_length (headers) > 0) {
5586                 TnyHeader *header = NULL;
5587                 TnyIterator *iter;
5588
5589                 iter = tny_list_create_iterator (headers);
5590                 header = (TnyHeader *) tny_iterator_get_current (iter);
5591                 src_folder = tny_header_get_folder (header);
5592
5593                 g_object_unref (header);
5594                 g_object_unref (iter);
5595
5596                 /* Transfer the messages */
5597                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5598                                                             TNY_FOLDER (dst_folder));
5599         }
5600
5601
5602         /* Frees */
5603         if (src_folder)
5604                 g_object_unref (src_folder);
5605         g_object_unref (headers);
5606 }
5607
5608 void 
5609 modest_ui_actions_on_move_to (GtkAction *action, 
5610                               ModestWindow *win)
5611 {
5612         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5613         gint result = 0;
5614         TnyFolderStore *dst_folder = NULL;
5615         ModestMainWindow *main_window;
5616
5617         g_return_if_fail (MODEST_IS_WINDOW (win));
5618
5619         /* Get the main window if exists */
5620         if (MODEST_IS_MAIN_WINDOW (win))
5621                 main_window = MODEST_MAIN_WINDOW (win);
5622         else
5623                 main_window = 
5624                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5625                                                                                FALSE)); /* don't create */
5626
5627         /* Get the folder view widget if exists */
5628         if (main_window)
5629                 folder_view = modest_main_window_get_child_widget (main_window,
5630                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5631         else
5632                 folder_view = NULL;
5633
5634         /* Create and run the dialog */
5635         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5636         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5637         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) win);
5638         result = gtk_dialog_run (GTK_DIALOG(dialog));
5639         g_object_ref (tree_view);
5640         gtk_widget_destroy (dialog);
5641
5642         if (result != GTK_RESPONSE_ACCEPT)
5643                 return;
5644
5645         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5646         /* Do window specific stuff */
5647         if (MODEST_IS_MAIN_WINDOW (win)) {
5648                 modest_ui_actions_on_main_window_move_to (action,
5649                                 folder_view,
5650                                 dst_folder,
5651                                 MODEST_MAIN_WINDOW (win));
5652         } else {
5653                 modest_ui_actions_on_window_move_to (action,
5654                                                      dst_folder,
5655                                                      MODEST_WINDOW (win));
5656         }
5657
5658         if (dst_folder)
5659                 g_object_unref (dst_folder);
5660 }
5661
5662 /*
5663  * Calls #HeadersFunc for each header already selected in the main
5664  * window or the message currently being shown in the msg view window
5665  */
5666 static void
5667 do_headers_action (ModestWindow *win, 
5668                    HeadersFunc func,
5669                    gpointer user_data)
5670 {
5671         TnyList *headers_list = NULL;
5672         TnyIterator *iter = NULL;
5673         TnyHeader *header = NULL;
5674         TnyFolder *folder = NULL;
5675
5676         /* Get headers */
5677         headers_list = get_selected_headers (win);
5678         if (!headers_list)
5679                 return;
5680
5681         /* Get the folder */
5682         iter = tny_list_create_iterator (headers_list);
5683         header = TNY_HEADER (tny_iterator_get_current (iter));
5684         if (header) {
5685                 folder = tny_header_get_folder (header);
5686                 g_object_unref (header);
5687         }
5688
5689         /* Call the function for each header */
5690         while (!tny_iterator_is_done (iter)) {
5691                 header = TNY_HEADER (tny_iterator_get_current (iter));
5692                 func (header, win, user_data);
5693                 g_object_unref (header);
5694                 tny_iterator_next (iter);
5695         }
5696
5697         /* Trick: do a poke status in order to speed up the signaling
5698            of observers */
5699         tny_folder_poke_status (folder);
5700
5701         /* Frees */
5702         g_object_unref (folder);
5703         g_object_unref (iter);
5704         g_object_unref (headers_list);
5705 }
5706
5707 void 
5708 modest_ui_actions_view_attachment (GtkAction *action,
5709                                    ModestWindow *window)
5710 {
5711         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5712                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5713         } else {
5714                 /* not supported window for this action */
5715                 g_return_if_reached ();
5716         }
5717 }
5718
5719 void
5720 modest_ui_actions_save_attachments (GtkAction *action,
5721                                     ModestWindow *window)
5722 {
5723         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5724
5725                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5726                         return;
5727
5728                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5729         } else {
5730                 /* not supported window for this action */
5731                 g_return_if_reached ();
5732         }
5733 }
5734
5735 void
5736 modest_ui_actions_remove_attachments (GtkAction *action,
5737                                       ModestWindow *window)
5738 {
5739         if (MODEST_IS_MAIN_WINDOW (window)) {
5740                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5741         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5742                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5743         } else {
5744                 /* not supported window for this action */
5745                 g_return_if_reached ();
5746         }
5747 }
5748
5749 void 
5750 modest_ui_actions_on_settings (GtkAction *action, 
5751                                ModestWindow *win)
5752 {
5753         GtkWidget *dialog;
5754
5755         dialog = modest_platform_get_global_settings_dialog ();
5756         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5757         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5758         gtk_widget_show_all (dialog);
5759
5760         gtk_dialog_run (GTK_DIALOG (dialog));
5761
5762         gtk_widget_destroy (dialog);
5763 }
5764
5765 void 
5766 modest_ui_actions_on_help (GtkAction *action, 
5767                            GtkWindow *win)
5768 {
5769         /* Help app is not available at all in fremantle */
5770 #ifndef MODEST_TOOLKIT_HILDON2
5771         const gchar *help_id;
5772
5773         g_return_if_fail (win && GTK_IS_WINDOW(win));
5774         
5775         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5776
5777         if (help_id)
5778                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5779 #endif
5780 }
5781
5782 void 
5783 modest_ui_actions_on_csm_help (GtkAction *action, 
5784                                GtkWindow *win)
5785 {
5786         /* Help app is not available at all in fremantle */
5787 #ifndef MODEST_TOOLKIT_HILDON2
5788
5789         const gchar* help_id = NULL;
5790         GtkWidget *folder_view;
5791         TnyFolderStore *folder_store;
5792
5793         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5794
5795         /* Get selected folder */
5796         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5797                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5798         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5799
5800         /* Switch help_id */
5801         if (folder_store && TNY_IS_FOLDER (folder_store))
5802                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5803
5804         if (folder_store)
5805                 g_object_unref (folder_store);
5806
5807         if (help_id)
5808                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5809         else
5810                 modest_ui_actions_on_help (action, win);
5811 #endif
5812 }
5813
5814 static void     
5815 retrieve_contents_cb (ModestMailOperation *mail_op, 
5816                       TnyHeader *header, 
5817                       gboolean canceled,
5818                       TnyMsg *msg,
5819                       GError *err,
5820                       gpointer user_data)
5821 {
5822         /* We only need this callback to show an error in case of
5823            memory low condition */
5824         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5825 }
5826
5827 static void
5828 retrieve_msg_contents_performer (gboolean canceled, 
5829                                  GError *err,
5830                                  GtkWindow *parent_window, 
5831                                  TnyAccount *account, 
5832                                  gpointer user_data)
5833 {
5834         ModestMailOperation *mail_op;
5835         TnyList *headers = TNY_LIST (user_data);
5836
5837         if (err || canceled) {
5838                 check_memory_full_error ((GtkWidget *) parent_window, err);
5839                 goto out;
5840         }
5841
5842         /* Create mail operation */
5843         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5844                                                                  modest_ui_actions_disk_operations_error_handler, 
5845                                                                  NULL, NULL);
5846         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5847         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5848
5849         /* Frees */
5850         g_object_unref (mail_op);
5851  out:
5852         g_object_unref (headers);
5853         g_object_unref (account);
5854 }
5855
5856 void 
5857 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5858                                             ModestWindow *window)
5859 {
5860         TnyList *headers = NULL;
5861         TnyAccount *account = NULL;
5862         TnyIterator *iter = NULL;
5863         TnyHeader *header = NULL;
5864         TnyFolder *folder = NULL;
5865
5866         /* Get headers */
5867         headers = get_selected_headers (window);
5868         if (!headers)
5869                 return;
5870
5871         /* Pick the account */
5872         iter = tny_list_create_iterator (headers);
5873         header = TNY_HEADER (tny_iterator_get_current (iter));
5874         folder = tny_header_get_folder (header);
5875         account = tny_folder_get_account (folder);
5876         g_object_unref (folder);
5877         g_object_unref (header);
5878         g_object_unref (iter);
5879
5880         /* Connect and perform the message retrieval */
5881         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5882                                              g_object_ref (account), 
5883                                              retrieve_msg_contents_performer, 
5884                                              g_object_ref (headers));
5885
5886         /* Frees */
5887         g_object_unref (account);
5888         g_object_unref (headers);
5889 }
5890
5891 void
5892 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5893 {
5894         g_return_if_fail (MODEST_IS_WINDOW (window));
5895
5896         /* Update dimmed */
5897         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5898 }
5899
5900 void
5901 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5902 {
5903         g_return_if_fail (MODEST_IS_WINDOW (window));
5904
5905         /* Update dimmed */
5906         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5907 }
5908
5909 void
5910 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5911                                           ModestWindow *window)
5912 {
5913         g_return_if_fail (MODEST_IS_WINDOW (window));
5914         
5915         /* Update dimmed */
5916         modest_ui_actions_check_menu_dimming_rules (window);
5917 }
5918
5919 void
5920 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5921                                           ModestWindow *window)
5922 {
5923         g_return_if_fail (MODEST_IS_WINDOW (window));
5924
5925         /* Update dimmed */
5926         modest_ui_actions_check_menu_dimming_rules (window);
5927 }
5928
5929 void
5930 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5931                                           ModestWindow *window)
5932 {
5933         g_return_if_fail (MODEST_IS_WINDOW (window));
5934
5935         /* Update dimmed */
5936         modest_ui_actions_check_menu_dimming_rules (window);
5937 }
5938
5939 void
5940 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5941                                             ModestWindow *window)
5942 {
5943         g_return_if_fail (MODEST_IS_WINDOW (window));
5944
5945         /* Update dimmed */
5946         modest_ui_actions_check_menu_dimming_rules (window);
5947 }
5948
5949 void
5950 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5951                                           ModestWindow *window)
5952 {
5953         g_return_if_fail (MODEST_IS_WINDOW (window));
5954
5955         /* Update dimmed */
5956         modest_ui_actions_check_menu_dimming_rules (window);
5957 }
5958
5959 void
5960 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5961                                           ModestWindow *window)
5962 {
5963         g_return_if_fail (MODEST_IS_WINDOW (window));
5964
5965         /* Update dimmed */
5966         modest_ui_actions_check_menu_dimming_rules (window);
5967 }
5968
5969 void
5970 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5971                                                  ModestWindow *window)
5972 {
5973         g_return_if_fail (MODEST_IS_WINDOW (window));
5974
5975         /* Update dimmed */
5976         modest_ui_actions_check_menu_dimming_rules (window);
5977 }
5978
5979 void
5980 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5981                                                      ModestWindow *window)
5982 {
5983         g_return_if_fail (MODEST_IS_WINDOW (window));
5984
5985         /* Update dimmed */
5986         modest_ui_actions_check_menu_dimming_rules (window);
5987 }
5988
5989 void
5990 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5991                                                      ModestWindow *window)
5992 {
5993         g_return_if_fail (MODEST_IS_WINDOW (window));
5994
5995         /* Update dimmed */
5996         modest_ui_actions_check_menu_dimming_rules (window);
5997 }
5998
5999 void
6000 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6001 {
6002         g_return_if_fail (MODEST_IS_WINDOW (window));
6003
6004         /* we check for low-mem; in that case, show a warning, and don't allow
6005          * searching
6006          */
6007         if (modest_platform_check_memory_low (window, TRUE))
6008                 return;
6009         
6010         modest_platform_show_search_messages (GTK_WINDOW (window));
6011 }
6012
6013 void     
6014 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6015 {
6016         g_return_if_fail (MODEST_IS_WINDOW (win));
6017
6018
6019         /* we check for low-mem; in that case, show a warning, and don't allow
6020          * for the addressbook
6021          */
6022         if (modest_platform_check_memory_low (win, TRUE))
6023                 return;
6024
6025
6026         modest_platform_show_addressbook (GTK_WINDOW (win));
6027 }
6028
6029
6030 void
6031 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
6032                                           ModestWindow *window)
6033 {
6034         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6035
6036         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
6037 }
6038
6039 static void 
6040 on_send_receive_finished (ModestMailOperation  *mail_op, 
6041                            gpointer user_data)
6042 {
6043         GtkWidget *header_view, *folder_view;
6044         TnyFolderStore *folder_store;
6045         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6046
6047         /* Set send/receive operation finished */       
6048         modest_main_window_notify_send_receive_completed (main_win);
6049
6050         /* Don't refresh the current folder if there were any errors */
6051         if (modest_mail_operation_get_status (mail_op) !=
6052             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6053                 return;
6054         
6055         /* Refresh the current folder if we're viewing a window. We do
6056            this because the user won't be able to see the new mails in
6057            the selected folder after a Send&Receive because it only
6058            performs a poke_status, i.e, only the number of read/unread
6059            messages is updated, but the new headers are not
6060            downloaded */
6061         folder_view = modest_main_window_get_child_widget (main_win, 
6062                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6063         if (!folder_view)
6064                 return;
6065
6066         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6067         
6068         /* Do not need to refresh INBOX again because the
6069            update_account does it always automatically */
6070         if (folder_store && TNY_IS_FOLDER (folder_store) && 
6071             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6072                 ModestMailOperation *refresh_op;
6073
6074                 header_view = modest_main_window_get_child_widget (main_win,
6075                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6076                 
6077                 /* We do not need to set the contents style
6078                    because it hasn't changed. We also do not
6079                    need to save the widget status. Just force
6080                    a refresh */
6081                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6082                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6083                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6084                                                       folder_refreshed_cb, main_win);
6085                 g_object_unref (refresh_op);
6086         }
6087         
6088         if (folder_store)
6089                 g_object_unref (folder_store);
6090 }
6091
6092
6093 void 
6094 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
6095                                                 TnyHeader *header, 
6096                                                 TnyMsg *msg, 
6097                                                 GError *err, 
6098                                                 gpointer user_data)
6099 {
6100         const gchar* server_name = NULL;
6101         TnyTransportAccount *server_account;
6102         gchar *message = NULL;
6103
6104         /* Don't show anything if the user cancelled something or the
6105          * send receive request is not interactive. Authentication
6106          * errors are managed by the account store so no need to show
6107          * a dialog here again */
6108         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6109             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6110             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6111                 return;
6112
6113
6114         /* Get the server name: */
6115         server_account = 
6116                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
6117         if (server_account)
6118                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
6119         else
6120                 g_return_if_reached ();
6121
6122         /* Show the appropriate message text for the GError: */
6123         switch (err->code) {
6124         case TNY_SERVICE_ERROR_CONNECT:
6125                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6126                 break;
6127         case TNY_SERVICE_ERROR_SEND:
6128                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6129                 break;
6130         case TNY_SERVICE_ERROR_UNAVAILABLE:
6131                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6132                 break;
6133         default:
6134                 g_warning ("%s: unexpected ERROR %d",
6135                            __FUNCTION__, err->code);
6136                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6137                 break;  
6138         }
6139
6140         modest_platform_run_information_dialog (NULL, message, FALSE);
6141         g_free (message);
6142         g_object_unref (server_account);
6143 }
6144
6145 void
6146 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6147                                                 gchar *msg_id, 
6148                                                 guint status,
6149                                                 gpointer user_data)
6150 {
6151         ModestMainWindow *main_window = NULL;
6152         ModestWindowMgr *mgr = NULL;
6153         GtkWidget *folder_view = NULL, *header_view = NULL;
6154         TnyFolderStore *selected_folder = NULL;
6155         TnyFolderType folder_type;
6156
6157         mgr = modest_runtime_get_window_mgr ();
6158         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6159                                                                              FALSE));/* don't create */
6160         if (!main_window)
6161                 return;
6162
6163         /* Check if selected folder is OUTBOX */
6164         folder_view = modest_main_window_get_child_widget (main_window,
6165                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6166         header_view = modest_main_window_get_child_widget (main_window,
6167                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6168
6169         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6170         if (!TNY_IS_FOLDER (selected_folder)) 
6171                 goto frees;
6172
6173         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6174 #if GTK_CHECK_VERSION(2, 8, 0) 
6175         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6176         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6177                 GtkTreeViewColumn *tree_column;
6178
6179                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6180                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6181                 if (tree_column)
6182                         gtk_tree_view_column_queue_resize (tree_column);
6183         }
6184 #else
6185         gtk_widget_queue_draw (header_view);
6186 #endif          
6187
6188         /* Rerun dimming rules, because the message could become deletable for example */
6189         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6190                                                  MODEST_DIMMING_RULES_TOOLBAR);
6191         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6192                                                  MODEST_DIMMING_RULES_MENU);
6193         
6194         /* Free */
6195  frees:
6196         if (selected_folder != NULL)
6197                 g_object_unref (selected_folder);
6198 }
6199
6200 void 
6201 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6202                                                TnyAccount *account)
6203 {
6204         ModestProtocolType protocol_type;
6205         ModestProtocol *protocol;
6206         gchar *error_note = NULL;
6207         
6208         protocol_type = modest_tny_account_get_protocol_type (account);
6209         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6210                                                                   protocol_type);
6211
6212         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6213         if (error_note == NULL) {
6214                 g_warning ("%s: This should not be reached", __FUNCTION__);
6215         } else {
6216                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6217                 g_free (error_note);
6218         }
6219 }
6220
6221 gchar *
6222 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6223 {
6224         gchar *msg = NULL;
6225         gchar *subject;
6226         TnyFolderStore *folder = NULL;
6227         TnyAccount *account = NULL;
6228         ModestProtocolType proto;
6229         ModestProtocol *protocol;
6230         TnyHeader *header = NULL;
6231
6232         if (MODEST_IS_MAIN_WINDOW (win)) {
6233                 GtkWidget *header_view;
6234                 TnyList* headers = NULL;
6235                 TnyIterator *iter;
6236                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6237                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6238                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6239                 if (!headers || tny_list_get_length (headers) == 0) {
6240                         if (headers)
6241                                 g_object_unref (headers);
6242                         return NULL;
6243                 }
6244                 iter = tny_list_create_iterator (headers);
6245                 header = TNY_HEADER (tny_iterator_get_current (iter));
6246                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6247                 g_object_unref (iter);
6248                 g_object_unref (headers);
6249         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6250                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6251                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6252         }
6253
6254         /* Get the account type */
6255         account = tny_folder_get_account (TNY_FOLDER (folder));
6256         proto = modest_tny_account_get_protocol_type (account);
6257         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6258                                                                   proto);
6259
6260         subject = tny_header_dup_subject (header);
6261         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6262         if (subject)
6263                 g_free (subject);
6264         if (msg == NULL) {
6265                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6266         }
6267
6268         /* Frees */
6269         g_object_unref (account);
6270         g_object_unref (folder);
6271         g_object_unref (header);
6272
6273         return msg;
6274 }
6275
6276 gboolean
6277 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6278                                      const gchar *account_name,
6279                                      const gchar *account_title)
6280 {
6281         ModestAccountMgr *account_mgr;
6282         gchar *txt = NULL;
6283         gint response;
6284         ModestProtocol *protocol;
6285         gboolean removed = FALSE;
6286
6287         g_return_val_if_fail (account_name, FALSE);
6288         g_return_val_if_fail (account_title, FALSE);
6289
6290         account_mgr = modest_runtime_get_account_mgr();
6291
6292         /* The warning text depends on the account type: */
6293         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6294                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6295                                                                                                          account_name));
6296         txt = modest_protocol_get_translation (protocol,
6297                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6298                                                account_title);
6299         if (txt == NULL)
6300                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6301
6302         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6303         g_free (txt);
6304         txt = NULL;
6305
6306         if (response == GTK_RESPONSE_OK) {
6307                 /* Remove account. If it succeeds then it also removes
6308                    the account from the ModestAccountView: */
6309                 gboolean is_default = FALSE;
6310                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6311                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6312                         is_default = TRUE;
6313                 g_free (default_account_name);
6314
6315                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6316                 if (!removed)
6317                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6318         }
6319         return removed;
6320 }