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