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