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