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