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