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