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