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