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