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