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