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