* Fixes NB#93489, remove the login cancelled message
[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 #ifdef MODEST_TOOLKIT_HILDON2
3603         GtkWidget *dialog =
3604                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3605                                              NULL,
3606                                              GTK_DIALOG_MODAL,
3607                                              _HL("wdgt_bd_done"),
3608                                              GTK_RESPONSE_ACCEPT,
3609                                              NULL);
3610 #else
3611         GtkWidget *dialog =
3612                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3613                                              NULL,
3614                                              _("mcen_bd_dialog_ok"),
3615                                              GTK_RESPONSE_ACCEPT,
3616                                              _("mcen_bd_dialog_cancel"),
3617                                              GTK_RESPONSE_REJECT,
3618                                              NULL);
3619 #endif /* MODEST_TOOLKIT_HILDON2 */
3620 #else
3621         GtkWidget *dialog = 
3622                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3623                                              NULL,
3624                                              GTK_DIALOG_MODAL,
3625                                              GTK_STOCK_CANCEL,
3626                                              GTK_RESPONSE_REJECT,
3627                                              GTK_STOCK_OK,
3628                                              GTK_RESPONSE_ACCEPT,
3629                                              NULL);
3630 #endif /* MODEST_TOOLKIT_GTK */
3631
3632         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3633
3634         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3635                 modest_runtime_get_account_mgr(), server_account_name);
3636         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3637                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3638                 if (cancel)
3639                         *cancel = TRUE;
3640                 gtk_widget_destroy (dialog);
3641                 return;
3642         }
3643
3644         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3645         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3646                             FALSE, FALSE, 0);
3647         g_free (txt);
3648         g_free (server_name);
3649         server_name = NULL;
3650
3651         /* username: */
3652         gchar *initial_username = modest_account_mgr_get_server_account_username (
3653                 modest_runtime_get_account_mgr(), server_account_name);
3654
3655         GtkWidget *entry_username = gtk_entry_new ();
3656         if (initial_username)
3657                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3658         /* Dim this if a connection has ever succeeded with this username,
3659          * as per the UI spec: */
3660         /* const gboolean username_known =  */
3661         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3662         /*              modest_runtime_get_account_mgr(), server_account_name); */
3663         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3664
3665         /* We drop the username sensitive code and disallow changing it here
3666          * as tinymail does not support really changing the username in the callback
3667          */
3668         gtk_widget_set_sensitive (entry_username, FALSE);
3669
3670 #ifndef MODEST_TOOLKIT_GTK
3671         /* Auto-capitalization is the default, so let's turn it off: */
3672         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3673
3674         /* Create a size group to be used by all captions.
3675          * Note that HildonCaption does not create a default size group if we do not specify one.
3676          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3677         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3678
3679         GtkWidget *caption = hildon_caption_new (sizegroup, 
3680                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3681         gtk_widget_show (entry_username);
3682         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3683                 FALSE, FALSE, MODEST_MARGIN_HALF);
3684         gtk_widget_show (caption);
3685 #else
3686         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3687                             TRUE, FALSE, 0);
3688 #endif /* !MODEST_TOOLKIT_GTK */
3689
3690         /* password: */
3691         GtkWidget *entry_password = gtk_entry_new ();
3692         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3693         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3694
3695 #ifndef MODEST_TOOLKIT_GTK
3696         /* Auto-capitalization is the default, so let's turn it off: */
3697         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3698                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3699
3700         caption = hildon_caption_new (sizegroup,
3701                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3702         gtk_widget_show (entry_password);
3703         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3704                 FALSE, FALSE, MODEST_MARGIN_HALF);
3705         gtk_widget_show (caption);
3706         g_object_unref (sizegroup);
3707 #else
3708         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3709                             TRUE, FALSE, 0);
3710 #endif /* !MODEST_TOOLKIT_GTK */
3711
3712         if (initial_username != NULL)
3713                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3714
3715 /* This is not in the Maemo UI spec:
3716         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3717         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3718                             TRUE, FALSE, 0);
3719 */
3720
3721         fields = g_slice_new0 (PasswordDialogFields);
3722         fields->username = entry_username;
3723         fields->password = entry_password;
3724         fields->dialog = dialog;
3725
3726         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3727         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3728         password_dialog_check_field (NULL, fields);
3729
3730         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3731
3732         while (!completed) {
3733
3734                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3735                         if (username) {
3736                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3737
3738                                 /* Note that an empty field becomes the "" string */
3739                                 if (*username && strlen (*username) > 0) {
3740                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3741                                                                                         server_account_name, 
3742                                                                                         *username);
3743                                         completed = TRUE;
3744
3745                                         const gboolean username_was_changed = 
3746                                                 (strcmp (*username, initial_username) != 0);
3747                                         if (username_was_changed) {
3748                                                 g_warning ("%s: tinymail does not yet support changing the "
3749                                                            "username in the get_password() callback.\n", __FUNCTION__);
3750                                         }
3751                                 } else {
3752                                         g_free (*username);
3753                                         *username = NULL;
3754                                         /* Show error */
3755                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3756                                                                             _("mcen_ib_username_pw_incorrect"));
3757                                         completed = FALSE;
3758                                 }
3759                         }
3760
3761                         if (password) {
3762                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3763
3764                                 /* We do not save the password in the configuration, 
3765                                  * because this function is only called for passwords that should 
3766                                  * not be remembered:
3767                                  modest_server_account_set_password (
3768                                  modest_runtime_get_account_mgr(), server_account_name, 
3769                                  *password);
3770                                  */
3771                         }
3772                         if (cancel)
3773                                 *cancel   = FALSE;
3774                 } else {
3775 #ifndef MODEST_TOOLKIT_HILDON2
3776                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3777                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3778 #endif
3779                         completed = TRUE;
3780                         if (username)
3781                                 *username = NULL;
3782                         if (password)
3783                                 *password = NULL;
3784                         if (cancel)
3785                                 *cancel   = TRUE;
3786                 }
3787         }
3788
3789 /* This is not in the Maemo UI spec:
3790         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3791                 *remember = TRUE;
3792         else
3793                 *remember = FALSE;
3794 */
3795
3796         g_free (initial_username);
3797         gtk_widget_destroy (dialog);
3798         g_slice_free (PasswordDialogFields, fields);
3799         
3800         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3801 }
3802
3803 void
3804 modest_ui_actions_on_cut (GtkAction *action,
3805                           ModestWindow *window)
3806 {
3807         GtkWidget *focused_widget;
3808         GtkClipboard *clipboard;
3809
3810         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3811         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3812         if (GTK_IS_EDITABLE (focused_widget)) {
3813                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3814                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3815                 gtk_clipboard_store (clipboard);
3816         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3817                 GtkTextBuffer *buffer;
3818
3819                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3820                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3821                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3822                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3823                         gtk_clipboard_store (clipboard);
3824                 }
3825         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3826                 TnyList *header_list = modest_header_view_get_selected_headers (
3827                                 MODEST_HEADER_VIEW (focused_widget));
3828                 gboolean continue_download = FALSE;
3829                 gint num_of_unc_msgs;
3830
3831                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3832
3833                 if (num_of_unc_msgs) {
3834                         TnyAccount *account = get_account_from_header_list (header_list);
3835                         if (account) {
3836                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3837                                 g_object_unref (account);
3838                         }
3839                 }
3840
3841                 if (num_of_unc_msgs == 0 || continue_download) {
3842 /*                      modest_platform_information_banner (
3843                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3844                         modest_header_view_cut_selection (
3845                                         MODEST_HEADER_VIEW (focused_widget));
3846                 }
3847
3848                 g_object_unref (header_list);
3849         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3850                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3851         }
3852 }
3853
3854 void
3855 modest_ui_actions_on_copy (GtkAction *action,
3856                            ModestWindow *window)
3857 {
3858         GtkClipboard *clipboard;
3859         GtkWidget *focused_widget;
3860         gboolean copied = TRUE;
3861
3862         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3863         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3864
3865         if (GTK_IS_LABEL (focused_widget)) {
3866                 gchar *selection;
3867                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3868                 gtk_clipboard_set_text (clipboard, selection, -1);
3869                 g_free (selection);
3870                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3871                 gtk_clipboard_store (clipboard);
3872         } else if (GTK_IS_EDITABLE (focused_widget)) {
3873                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3874                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3875                 gtk_clipboard_store (clipboard);
3876         } else if (GTK_IS_HTML (focused_widget)) {
3877                 const gchar *sel;
3878                 int len = -1;
3879                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3880                 if ((sel == NULL) || (sel[0] == '\0')) {
3881                         copied = FALSE;
3882                 } else {
3883                         gtk_html_copy (GTK_HTML (focused_widget));
3884                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3885                         gtk_clipboard_store (clipboard);
3886                 }
3887         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3888                 GtkTextBuffer *buffer;
3889                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3890                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3891                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3892                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3893                         gtk_clipboard_store (clipboard);
3894                 }
3895         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3896                 TnyList *header_list = modest_header_view_get_selected_headers (
3897                                 MODEST_HEADER_VIEW (focused_widget));
3898                 gboolean continue_download = FALSE;
3899                 gint num_of_unc_msgs;
3900
3901                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3902
3903                 if (num_of_unc_msgs) {
3904                         TnyAccount *account = get_account_from_header_list (header_list);
3905                         if (account) {
3906                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3907                                 g_object_unref (account);
3908                         }
3909                 }
3910
3911                 if (num_of_unc_msgs == 0 || continue_download) {
3912                         modest_platform_information_banner (
3913                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3914                         modest_header_view_copy_selection (
3915                                         MODEST_HEADER_VIEW (focused_widget));
3916                 } else
3917                         copied = FALSE;
3918
3919                 g_object_unref (header_list);
3920
3921         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3922                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3923         }
3924
3925         /* Show information banner if there was a copy to clipboard */
3926         if(copied)
3927                 modest_platform_information_banner (
3928                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3929 }
3930
3931 void
3932 modest_ui_actions_on_undo (GtkAction *action,
3933                            ModestWindow *window)
3934 {
3935         ModestEmailClipboard *clipboard = NULL;
3936
3937         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3938                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3939         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3940                 /* Clear clipboard source */
3941                 clipboard = modest_runtime_get_email_clipboard ();
3942                 modest_email_clipboard_clear (clipboard);               
3943         }
3944         else {
3945                 g_return_if_reached ();
3946         }
3947 }
3948
3949 void
3950 modest_ui_actions_on_redo (GtkAction *action,
3951                            ModestWindow *window)
3952 {
3953         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3954                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3955         }
3956         else {
3957                 g_return_if_reached ();
3958         }
3959 }
3960
3961
3962 static void
3963 destroy_information_note (ModestMailOperation *mail_op, 
3964                           gpointer user_data)
3965 {
3966         /* destroy information note */
3967         gtk_widget_destroy (GTK_WIDGET(user_data));
3968 }
3969
3970 static void
3971 destroy_folder_information_note (ModestMailOperation *mail_op, 
3972                                  TnyFolder *new_folder,
3973                                  gpointer user_data)
3974 {
3975         /* destroy information note */
3976         gtk_widget_destroy (GTK_WIDGET(user_data));
3977 }
3978
3979
3980 static void
3981 paste_as_attachment_free (gpointer data)
3982 {
3983         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3984
3985         if (helper->banner) {
3986                 gtk_widget_destroy (helper->banner);
3987                 g_object_unref (helper->banner);
3988         }
3989         g_free (helper);
3990 }
3991
3992 static void
3993 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3994                             TnyHeader *header,
3995                             TnyMsg *msg,
3996                             gpointer userdata)
3997 {
3998         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3999         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4000
4001         if (msg == NULL)
4002                 return;
4003
4004         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4005         
4006 }
4007
4008 void
4009 modest_ui_actions_on_paste (GtkAction *action,
4010                             ModestWindow *window)
4011 {
4012         GtkWidget *focused_widget = NULL;
4013         GtkWidget *inf_note = NULL;
4014         ModestMailOperation *mail_op = NULL;
4015
4016         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4017         if (GTK_IS_EDITABLE (focused_widget)) {
4018                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4019         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4020                 ModestEmailClipboard *e_clipboard = NULL;
4021                 e_clipboard = modest_runtime_get_email_clipboard ();
4022                 if (modest_email_clipboard_cleared (e_clipboard)) {
4023                         GtkTextBuffer *buffer;
4024                         GtkClipboard *clipboard;
4025
4026                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4027                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4028                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4029                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4030                         ModestMailOperation *mail_op;
4031                         TnyFolder *src_folder = NULL;
4032                         TnyList *data = NULL;
4033                         gboolean delete;
4034                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4035                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4036                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4037                                                                            _CS("ckct_nw_pasting"));
4038                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4039                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4040                         if (helper->banner != NULL) {
4041                                 g_object_ref (G_OBJECT (helper->banner));
4042                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4043                         }
4044
4045                         if (data != NULL) {
4046                                 modest_mail_operation_get_msgs_full (mail_op, 
4047                                                                      data,
4048                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4049                                                                      helper,
4050                                                                      paste_as_attachment_free);
4051                         }
4052                         /* Free */
4053                         if (data) 
4054                                 g_object_unref (data);
4055                         if (src_folder) 
4056                                 g_object_unref (src_folder);
4057
4058                 }
4059         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4060                 ModestEmailClipboard *clipboard = NULL;
4061                 TnyFolder *src_folder = NULL;
4062                 TnyFolderStore *folder_store = NULL;
4063                 TnyList *data = NULL;           
4064                 gboolean delete = FALSE;
4065                 
4066                 /* Check clipboard source */
4067                 clipboard = modest_runtime_get_email_clipboard ();
4068                 if (modest_email_clipboard_cleared (clipboard)) 
4069                         return;
4070                 
4071                 /* Get elements to paste */
4072                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4073
4074                 /* Create a new mail operation */
4075                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4076                 
4077                 /* Get destination folder */
4078                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4079
4080                 /* transfer messages  */
4081                 if (data != NULL) {
4082                         gint response = 0;
4083
4084                         /* Ask for user confirmation */
4085                         response = 
4086                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4087                                                                              TNY_FOLDER (folder_store), 
4088                                                                              delete,
4089                                                                              data);
4090                         
4091                         if (response == GTK_RESPONSE_OK) {
4092                                 /* Launch notification */
4093                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4094                                                                              _CS("ckct_nw_pasting"));
4095                                 if (inf_note != NULL)  {
4096                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4097                                         gtk_widget_show (GTK_WIDGET(inf_note));
4098                                 }
4099
4100                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4101                                 modest_mail_operation_xfer_msgs (mail_op, 
4102                                                                  data,
4103                                                                  TNY_FOLDER (folder_store),
4104                                                                  delete,
4105                                                                  destroy_information_note,
4106                                                                  inf_note);                             
4107                         } else {
4108                                 g_object_unref (mail_op);
4109                         }
4110                         
4111                 } else if (src_folder != NULL) {                        
4112                         /* Launch notification */
4113                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4114                                                                      _CS("ckct_nw_pasting"));
4115                         if (inf_note != NULL)  {
4116                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4117                                 gtk_widget_show (GTK_WIDGET(inf_note));
4118                         }
4119                         
4120                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4121                         modest_mail_operation_xfer_folder (mail_op, 
4122                                                            src_folder,
4123                                                            folder_store,
4124                                                            delete,
4125                                                            destroy_folder_information_note,
4126                                                            inf_note);
4127                 }
4128
4129                 /* Free */
4130                 if (data != NULL) 
4131                         g_object_unref (data);
4132                 if (src_folder != NULL) 
4133                         g_object_unref (src_folder);
4134                 if (folder_store != NULL) 
4135                         g_object_unref (folder_store);
4136         }
4137 }
4138
4139
4140 void
4141 modest_ui_actions_on_select_all (GtkAction *action,
4142                                  ModestWindow *window)
4143 {
4144         GtkWidget *focused_widget;
4145
4146         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4147         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4148                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4149         } else if (GTK_IS_LABEL (focused_widget)) {
4150                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4151         } else if (GTK_IS_EDITABLE (focused_widget)) {
4152                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4153         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4154                 GtkTextBuffer *buffer;
4155                 GtkTextIter start, end;
4156
4157                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4158                 gtk_text_buffer_get_start_iter (buffer, &start);
4159                 gtk_text_buffer_get_end_iter (buffer, &end);
4160                 gtk_text_buffer_select_range (buffer, &start, &end);
4161         } else if (GTK_IS_HTML (focused_widget)) {
4162                 gtk_html_select_all (GTK_HTML (focused_widget));
4163         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4164                 GtkWidget *header_view = focused_widget;
4165                 GtkTreeSelection *selection = NULL;
4166                 
4167                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4168                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4169                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4170                 }
4171                                 
4172                 /* Disable window dimming management */
4173                 modest_window_disable_dimming (MODEST_WINDOW(window));
4174                 
4175                 /* Select all messages */
4176                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4177                 gtk_tree_selection_select_all (selection);
4178
4179                 /* Set focuse on header view */
4180                 gtk_widget_grab_focus (header_view);
4181
4182                 /* Enable window dimming management */
4183                 modest_window_enable_dimming (MODEST_WINDOW(window));
4184                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4185                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4186         }
4187
4188 }
4189
4190 void
4191 modest_ui_actions_on_mark_as_read (GtkAction *action,
4192                                    ModestWindow *window)
4193 {       
4194         g_return_if_fail (MODEST_IS_WINDOW(window));
4195                 
4196         /* Mark each header as read */
4197         do_headers_action (window, headers_action_mark_as_read, NULL);
4198 }
4199
4200 void
4201 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4202                                      ModestWindow *window)
4203 {       
4204         g_return_if_fail (MODEST_IS_WINDOW(window));
4205                 
4206         /* Mark each header as read */
4207         do_headers_action (window, headers_action_mark_as_unread, NULL);
4208 }
4209
4210 void
4211 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4212                                   GtkRadioAction *selected,
4213                                   ModestWindow *window)
4214 {
4215         gint value;
4216
4217         value = gtk_radio_action_get_current_value (selected);
4218         if (MODEST_IS_WINDOW (window)) {
4219                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4220         }
4221 }
4222
4223 void
4224 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4225                                                GtkRadioAction *selected,
4226                                                ModestWindow *window)
4227 {
4228         TnyHeaderFlags flags;
4229         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4230
4231         flags = gtk_radio_action_get_current_value (selected);
4232         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4233 }
4234
4235 void
4236 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4237                                                   GtkRadioAction *selected,
4238                                                   ModestWindow *window)
4239 {
4240         gint file_format;
4241
4242         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4243
4244         file_format = gtk_radio_action_get_current_value (selected);
4245         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4246 }
4247
4248
4249 void
4250 modest_ui_actions_on_zoom_plus (GtkAction *action,
4251                                 ModestWindow *window)
4252 {
4253         g_return_if_fail (MODEST_IS_WINDOW (window));
4254
4255         modest_window_zoom_plus (MODEST_WINDOW (window));
4256 }
4257
4258 void     
4259 modest_ui_actions_on_zoom_minus (GtkAction *action,
4260                                  ModestWindow *window)
4261 {
4262         g_return_if_fail (MODEST_IS_WINDOW (window));
4263
4264         modest_window_zoom_minus (MODEST_WINDOW (window));
4265 }
4266
4267 void     
4268 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4269                                            ModestWindow *window)
4270 {
4271         ModestWindowMgr *mgr;
4272         gboolean fullscreen, active;
4273         g_return_if_fail (MODEST_IS_WINDOW (window));
4274
4275         mgr = modest_runtime_get_window_mgr ();
4276
4277         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4278         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4279
4280         if (active != fullscreen) {
4281                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4282 #ifndef MODEST_TOOLKIT_HILDON2
4283                 gtk_window_present (GTK_WINDOW (window));
4284 #endif
4285         }
4286 }
4287
4288 void
4289 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4290                                         ModestWindow *window)
4291 {
4292         ModestWindowMgr *mgr;
4293         gboolean fullscreen;
4294
4295         g_return_if_fail (MODEST_IS_WINDOW (window));
4296
4297         mgr = modest_runtime_get_window_mgr ();
4298         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4299         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4300
4301 #ifndef MODEST_TOOLKIT_HILDON2
4302         gtk_window_present (GTK_WINDOW (window));
4303 #endif
4304 }
4305
4306 /* 
4307  * Used by modest_ui_actions_on_details to call do_headers_action 
4308  */
4309 static void
4310 headers_action_show_details (TnyHeader *header, 
4311                              ModestWindow *window,
4312                              gpointer user_data)
4313
4314 {
4315         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header);
4316 }
4317
4318 /*
4319  * Show the header details in a ModestDetailsDialog widget
4320  */
4321 void     
4322 modest_ui_actions_on_details (GtkAction *action, 
4323                               ModestWindow *win)
4324 {
4325         TnyList * headers_list;
4326         TnyIterator *iter;
4327         TnyHeader *header;              
4328
4329         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4330                 TnyMsg *msg;
4331
4332                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4333                 if (!msg)
4334                         return;
4335                 g_object_unref (msg);           
4336
4337                 headers_list = get_selected_headers (win);
4338                 if (!headers_list)
4339                         return;
4340
4341                 iter = tny_list_create_iterator (headers_list);
4342
4343                 header = TNY_HEADER (tny_iterator_get_current (iter));
4344                 if (header) {
4345                         headers_action_show_details (header, win, NULL);
4346                         g_object_unref (header);
4347                 }
4348
4349                 g_object_unref (iter);
4350                 g_object_unref (headers_list);
4351
4352         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4353                 GtkWidget *folder_view, *header_view;
4354
4355                 /* Check which widget has the focus */
4356                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4357                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4358                 if (gtk_widget_is_focus (folder_view)) {
4359                         TnyFolderStore *folder_store
4360                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4361                         if (!folder_store) {
4362                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4363                                 return; 
4364                         }
4365                         /* Show only when it's a folder */
4366                         /* This function should not be called for account items, 
4367                          * because we dim the menu item for them. */
4368                         if (TNY_IS_FOLDER (folder_store)) {
4369                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win), 
4370                                                                            TNY_FOLDER (folder_store));
4371                         }
4372
4373                         g_object_unref (folder_store);
4374
4375                 } else {
4376                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4377                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4378                         /* Show details of each header */
4379                         do_headers_action (win, headers_action_show_details, header_view);
4380                 }
4381 #ifdef MODEST_TOOLKIT_HILDON2
4382         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4383                 TnyFolder *folder;
4384                 GtkWidget *header_view;
4385
4386                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4387                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4388                 if (folder) {
4389                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win), 
4390                                                                    folder);
4391                         g_object_unref (folder);
4392                 }
4393 #endif
4394         }
4395 }
4396
4397 void     
4398 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4399                                      ModestMsgEditWindow *window)
4400 {
4401         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4402
4403         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4404 }
4405
4406 void     
4407 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4408                                       ModestMsgEditWindow *window)
4409 {
4410         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4411
4412         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4413 }
4414
4415 void
4416 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4417                                        ModestMainWindow *main_window)
4418 {
4419         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4420
4421         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4422                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4423         else
4424                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4425 }
4426
4427 void 
4428 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4429                                      ModestWindow *window)
4430 {
4431         gboolean active, fullscreen = FALSE;
4432         ModestWindowMgr *mgr;
4433
4434         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4435
4436         /* Check if we want to toggle the toolbar view in fullscreen
4437            or normal mode */
4438         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4439                      "ViewShowToolbarFullScreen")) {
4440                 fullscreen = TRUE;
4441         }
4442
4443         /* Toggle toolbar */
4444         mgr = modest_runtime_get_window_mgr ();
4445         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4446 }
4447
4448 void     
4449 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4450                                            ModestMsgEditWindow *window)
4451 {
4452         modest_msg_edit_window_select_font (window);
4453 }
4454
4455
4456 void
4457 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4458                                                   const gchar *display_name,
4459                                                   GtkWindow *window)
4460 {
4461         /* don't update the display name if it was already set;
4462          * updating the display name apparently is expensive */
4463         const gchar* old_name = gtk_window_get_title (window);
4464
4465         if (display_name == NULL)
4466                 display_name = " ";
4467
4468         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4469                 return; /* don't do anything */
4470
4471         /* This is usually used to change the title of the main window, which
4472          * is the one that holds the folder view. Note that this change can
4473          * happen even when the widget doesn't have the focus. */
4474         gtk_window_set_title (window, display_name);
4475
4476 }
4477
4478 void
4479 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4480 {
4481         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4482         modest_msg_edit_window_select_contacts (window);
4483 }
4484
4485 void
4486 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4487 {
4488         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4489         modest_msg_edit_window_check_names (window, FALSE);
4490 }
4491
4492 static void
4493 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4494 {
4495         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4496                                          GTK_WIDGET (user_data));
4497 }
4498
4499 /*
4500  * This function is used to track changes in the selection of the
4501  * folder view that is inside the "move to" dialog to enable/disable
4502  * the OK button because we do not want the user to select a disallowed
4503  * destination for a folder.
4504  * The user also not desired to be able to use NEW button on items where
4505  * folder creation is not possibel.
4506  */
4507 static void
4508 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4509                                             TnyFolderStore *folder_store,
4510                                             gboolean selected,
4511                                             gpointer user_data)
4512 {
4513         GtkWidget *dialog = NULL;
4514         GtkWidget *ok_button = NULL, *new_button = NULL;
4515         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4516         gboolean moving_folder = FALSE;
4517         gboolean is_local_account = TRUE;
4518         GtkWidget *folder_view = NULL;
4519         ModestTnyFolderRules rules;
4520
4521         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4522         
4523         if (!selected)
4524                 return;
4525         
4526         /* Get the OK button */
4527         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4528         if (!dialog)
4529                 return;
4530
4531         ok_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON);
4532         new_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON);
4533
4534         /* check if folder_store is an remote account */
4535         if (TNY_IS_ACCOUNT (folder_store)) {
4536                 TnyAccount *local_account = NULL;
4537                 TnyAccount *mmc_account = NULL;
4538                 ModestTnyAccountStore *account_store = NULL;
4539
4540                 account_store = modest_runtime_get_account_store ();
4541                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4542                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4543
4544                 if ((gpointer) local_account != (gpointer) folder_store &&
4545                     (gpointer) mmc_account != (gpointer) folder_store) {
4546                         ModestProtocolType proto;
4547                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4548                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4549                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4550                         }
4551                         is_local_account = FALSE;
4552                         /* New button should be dimmed on remote
4553                            POP account root */
4554                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4555                                                                                          proto,
4556                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4557                 }
4558                 g_object_unref (local_account);
4559
4560                 /* It could not exist */
4561                 if (mmc_account)
4562                         g_object_unref (mmc_account);
4563         }
4564
4565         /* Check the target folder rules */
4566         if (TNY_IS_FOLDER (folder_store)) {
4567                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4568                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4569                         ok_sensitive = FALSE;
4570                         new_sensitive = FALSE;
4571                         goto end;
4572                 }
4573         }
4574
4575         /* Check if we're moving a folder */
4576         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4577                 /* Get the widgets */
4578                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4579                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4580                 if (gtk_widget_is_focus (folder_view))
4581                         moving_folder = TRUE;
4582         }
4583
4584         if (moving_folder) {
4585                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4586
4587                 /* Get the folder to move */
4588                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4589                 
4590                 /* Check that we're not moving to the same folder */
4591                 if (TNY_IS_FOLDER (moved_folder)) {
4592                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4593                         if (parent == folder_store)
4594                                 ok_sensitive = FALSE;
4595                         g_object_unref (parent);
4596                 } 
4597
4598                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4599                         /* Do not allow to move to an account unless it's the
4600                            local folders account */
4601                         if (!is_local_account)
4602                                 ok_sensitive = FALSE;
4603                 } 
4604
4605                 if (ok_sensitive && (moved_folder == folder_store)) {
4606                         /* Do not allow to move to itself */
4607                         ok_sensitive = FALSE;
4608                 }
4609                 g_object_unref (moved_folder);
4610         } else {
4611                 TnyFolder *src_folder = NULL;
4612
4613                 /* Moving a message */
4614                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4615
4616                         TnyHeader *header = NULL;
4617                         header = modest_msg_view_window_get_header
4618                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4619                         if (!TNY_IS_HEADER(header))
4620                                 g_warning ("%s: could not get source header", __FUNCTION__);
4621                         else
4622                                 src_folder = tny_header_get_folder (header);
4623
4624                         if (header)
4625                                 g_object_unref (header);
4626                 } else {
4627                         src_folder = 
4628                                 TNY_FOLDER (modest_folder_view_get_selected
4629                                             (MODEST_FOLDER_VIEW (folder_view)));
4630                 }
4631
4632                 if (TNY_IS_FOLDER(src_folder)) {
4633                         /* Do not allow to move the msg to the same folder */
4634                         /* Do not allow to move the msg to an account */
4635                         if ((gpointer) src_folder == (gpointer) folder_store ||
4636                             TNY_IS_ACCOUNT (folder_store))
4637                                 ok_sensitive = FALSE;
4638                         g_object_unref (src_folder);
4639                 } else
4640                         g_warning ("%s: could not get source folder", __FUNCTION__);
4641         }
4642
4643  end:
4644         /* Set sensitivity of the OK button */
4645         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4646         /* Set sensitivity of the NEW button */
4647         gtk_widget_set_sensitive (new_button, new_sensitive);
4648 }
4649
4650
4651 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4652
4653 static GtkWidget*
4654 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4655 {
4656         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4657                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4658 }
4659
4660 static GtkWidget*
4661 create_move_to_dialog (GtkWindow *win,
4662                        GtkWidget *folder_view,
4663                        GtkWidget **tree_view)
4664 {
4665         GtkWidget *dialog;
4666 #ifdef MODEST_TOOLKIT_HILDON2
4667         GtkWidget *pannable;
4668 #else
4669         GtkWidget *scroll;
4670 #endif
4671         GtkWidget *new_button, *ok_button;
4672
4673         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4674                                               GTK_WINDOW (win),
4675                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4676                                               NULL);
4677
4678 #ifndef MODEST_TOOLKIT_GTK
4679         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4680         /* We do this manually so GTK+ does not associate a response ID for
4681          * the button. */
4682         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4683         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4684         gtk_widget_show (new_button);
4685 #ifndef MODEST_TOOLKIT_HILDON2
4686         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4687 #endif
4688 #else
4689         /* We do this manually so GTK+ does not associate a response ID for
4690          * the button. */
4691         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4692         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4693         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4694         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4695         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4696         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4697         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4698 #endif
4699         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON, ok_button);
4700         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON, new_button);
4701
4702         /* Create scrolled window */
4703 #ifdef MODEST_TOOLKIT_HILDON2
4704         pannable = hildon_pannable_area_new ();
4705 #else
4706         scroll = gtk_scrolled_window_new (NULL, NULL);
4707         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4708                                          GTK_POLICY_AUTOMATIC,
4709                                          GTK_POLICY_AUTOMATIC);
4710 #endif
4711
4712 #ifdef MODEST_TOOLKIT_GTK
4713         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4714 #endif
4715
4716         /* Create folder view */
4717         *tree_view = modest_platform_create_folder_view (NULL);
4718
4719         /* Track changes in the selection to
4720          * disable the OK button whenever "Move to" is not possible
4721          * disbale NEW button whenever New is not possible */
4722         g_signal_connect (*tree_view,
4723                           "folder_selection_changed",
4724                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4725                           win);
4726
4727         /* Listen to clicks on New button */
4728         g_signal_connect (G_OBJECT (new_button), 
4729                           "clicked", 
4730                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4731                           *tree_view);
4732
4733         /* It could happen that we're trying to move a message from a
4734            window (msg window for example) after the main window was
4735            closed, so we can not just get the model of the folder
4736            view */
4737         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4738                 const gchar *visible_id = NULL;
4739
4740                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4741                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4742                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4743                                                MODEST_FOLDER_VIEW(*tree_view));
4744
4745                 visible_id = 
4746                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4747
4748                 /* Show the same account than the one that is shown in the main window */
4749                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4750                                                                              visible_id);
4751         } else {
4752                 const gchar *active_account_name = NULL;
4753                 ModestAccountMgr *mgr = NULL;
4754                 ModestAccountSettings *settings = NULL;
4755                 ModestServerAccountSettings *store_settings = NULL;
4756
4757                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4758                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4759                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4760                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4761
4762                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4763                 mgr = modest_runtime_get_account_mgr ();
4764                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4765
4766                 if (settings) {
4767                         const gchar *store_account_name;
4768                         store_settings = modest_account_settings_get_store_settings (settings);
4769                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4770
4771                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4772                                                                                      store_account_name);
4773                         g_object_unref (store_settings);
4774                         g_object_unref (settings);
4775                 }
4776         }
4777
4778         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4779          *   get_folder_view_from_move_to_dialog 
4780          * (see above) later (needed for focus handling) 
4781          */
4782         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4783
4784         
4785         /* Hide special folders */
4786         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4787
4788 #ifdef MODEST_TOOLKIT_HILDON2
4789         gtk_container_add (GTK_CONTAINER (pannable), *tree_view);
4790         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4791                             pannable, TRUE, TRUE, 0);
4792 #else
4793         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4794         /* Add scroll to dialog */
4795         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4796                             scroll, TRUE, TRUE, 0);
4797 #endif
4798
4799
4800         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4801 #ifndef MODEST_TOOLKIT_GTK
4802         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4803 #else
4804         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4805 #endif
4806
4807         return dialog;
4808 }
4809
4810
4811
4812 /*
4813  * Shows a confirmation dialog to the user when we're moving messages
4814  * from a remote server to the local storage. Returns the dialog
4815  * response. If it's other kind of movement then it always returns
4816  * GTK_RESPONSE_OK
4817  *
4818  * This one is used by the next functions:
4819  *      modest_ui_actions_on_paste                      - commented out
4820  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4821  */
4822 gint
4823 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4824                                              TnyFolder *dest_folder,
4825                                              gboolean delete,
4826                                              TnyList *headers)
4827 {
4828         gint response = GTK_RESPONSE_OK;
4829         TnyAccount *account = NULL;
4830         TnyFolder *src_folder = NULL;
4831         TnyIterator *iter = NULL;
4832         TnyHeader *header = NULL;
4833
4834         /* return with OK if the destination is a remote folder */
4835         if (modest_tny_folder_is_remote_folder (dest_folder))
4836                 return GTK_RESPONSE_OK;
4837
4838         /* Get source folder */
4839         iter = tny_list_create_iterator (headers);
4840         header = TNY_HEADER (tny_iterator_get_current (iter));
4841         if (header) {
4842                 src_folder = tny_header_get_folder (header);
4843                 g_object_unref (header);
4844         }
4845         g_object_unref (iter);
4846
4847         /* if no src_folder, message may be an attahcment */
4848         if (src_folder == NULL) 
4849                 return GTK_RESPONSE_CANCEL;
4850
4851         /* If the source is a local or MMC folder */
4852         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4853                 g_object_unref (src_folder);
4854                 return GTK_RESPONSE_OK;
4855         }
4856
4857         /* Get the account */
4858         account = tny_folder_get_account (src_folder);
4859
4860         /* now if offline we ask the user */
4861         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4862                 response = GTK_RESPONSE_OK;
4863         else
4864                 response = GTK_RESPONSE_CANCEL;
4865
4866         /* Frees */
4867         g_object_unref (src_folder);
4868         g_object_unref (account);
4869
4870         return response;
4871 }
4872
4873 static void
4874 move_to_helper_destroyer (gpointer user_data)
4875 {
4876         MoveToHelper *helper = (MoveToHelper *) user_data;
4877
4878         /* Close the "Pasting" information banner */
4879         if (helper->banner) {
4880                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4881                 g_object_unref (helper->banner);
4882         }
4883         if (gtk_tree_row_reference_valid (helper->reference)) {
4884                 gtk_tree_row_reference_free (helper->reference);
4885                 helper->reference = NULL;
4886         }
4887         g_free (helper);
4888 }
4889
4890 static void
4891 move_to_cb (ModestMailOperation *mail_op, 
4892             gpointer user_data)
4893 {
4894         MoveToHelper *helper = (MoveToHelper *) user_data;
4895
4896         /* Note that the operation could have failed, in that case do
4897            nothing */
4898         if (modest_mail_operation_get_status (mail_op) == 
4899             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4900
4901                 GObject *object = modest_mail_operation_get_source (mail_op);
4902                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4903                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4904
4905                         if (!modest_msg_view_window_select_next_message (self) &&
4906                             !modest_msg_view_window_select_previous_message (self)) {
4907                                 /* No more messages to view, so close this window */
4908                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4909                         }
4910                 } else if (MODEST_IS_MAIN_WINDOW (object) && 
4911                            gtk_tree_row_reference_valid (helper->reference)) {
4912                         GtkWidget *header_view;
4913                         GtkTreePath *path;
4914                         GtkTreeSelection *sel;
4915
4916                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4917                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4918                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4919                         path = gtk_tree_row_reference_get_path (helper->reference);
4920                         /* We need to unselect the previous one
4921                            because we could be copying instead of
4922                            moving */
4923                         gtk_tree_selection_unselect_all (sel);
4924                         gtk_tree_selection_select_path (sel, path);
4925                         gtk_tree_path_free (path);
4926                 }
4927                 g_object_unref (object);
4928         }
4929         /* Destroy the helper */
4930         move_to_helper_destroyer (helper);
4931 }
4932
4933 static void
4934 folder_move_to_cb (ModestMailOperation *mail_op, 
4935                    TnyFolder *new_folder,
4936                    gpointer user_data)
4937 {
4938         GtkWidget *folder_view;
4939         GObject *object;
4940
4941         object = modest_mail_operation_get_source (mail_op);
4942         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4943                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4944         g_object_ref (folder_view);
4945         g_object_unref (object);
4946         move_to_cb (mail_op, user_data);
4947         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4948         g_object_unref (folder_view);
4949 }
4950
4951 static void
4952 msgs_move_to_cb (ModestMailOperation *mail_op, 
4953                  gpointer user_data)
4954 {
4955         move_to_cb (mail_op, user_data);
4956 }
4957
4958 void
4959 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4960                                              gpointer user_data)
4961 {
4962         ModestWindow *main_window = NULL;
4963         
4964         /* Disable next automatic folder selection */
4965         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4966                                                          FALSE); /* don't create */
4967         if (main_window) {
4968                 GObject *win = NULL;
4969                 GtkWidget *folder_view = NULL;
4970         
4971                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4972                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4973                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4974                 
4975                 if (user_data && TNY_IS_FOLDER (user_data)) {
4976                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4977                                                           TNY_FOLDER (user_data), FALSE);
4978                 }
4979
4980                 /* Show notification dialog only if the main window exists */
4981                 win = modest_mail_operation_get_source (mail_op);
4982                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4983                                                         _("mail_in_ui_folder_move_target_error"), 
4984                                                         FALSE);
4985                 if (win)
4986                         g_object_unref (win);
4987         }
4988 }
4989
4990 static void
4991 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4992                        TnyHeader *header, 
4993                        gboolean canceled,
4994                        TnyMsg *msg, 
4995                        GError *err,
4996                        gpointer user_data)
4997 {
4998         TnyList *parts;
4999         TnyIterator *iter;
5000         gint pending_purges = 0;
5001         gboolean some_purged = FALSE;
5002         ModestWindow *win = MODEST_WINDOW (user_data);
5003         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5004
5005         /* If there was any error */
5006         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5007                 modest_window_mgr_unregister_header (mgr, header);
5008                 return;
5009         }
5010
5011         /* Once the message has been retrieved for purging, we check if
5012          * it's all ok for purging */
5013
5014         parts = tny_simple_list_new ();
5015         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5016         iter = tny_list_create_iterator (parts);
5017
5018         while (!tny_iterator_is_done (iter)) {
5019                 TnyMimePart *part;
5020                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5021                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5022                         if (tny_mime_part_is_purged (part))
5023                                 some_purged = TRUE;
5024                         else
5025                                 pending_purges++;
5026                 }
5027
5028                 if (part)
5029                         g_object_unref (part);
5030
5031                 tny_iterator_next (iter);
5032         }
5033         g_object_unref (iter);
5034         
5035
5036         if (pending_purges>0) {
5037                 gint response;
5038                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5039
5040                 if (response == GTK_RESPONSE_OK) {
5041                         GtkWidget *info;
5042                         info =
5043                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5044                         iter = tny_list_create_iterator (parts);
5045                         while (!tny_iterator_is_done (iter)) {
5046                                 TnyMimePart *part;
5047                                 
5048                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5049                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5050                                         tny_mime_part_set_purged (part);
5051
5052                                 if (part)
5053                                         g_object_unref (part);
5054
5055                                 tny_iterator_next (iter);
5056                         }
5057                         g_object_unref (iter);
5058                         
5059                         tny_msg_rewrite_cache (msg);
5060
5061                         gtk_widget_destroy (info);
5062                 }
5063         }
5064
5065         modest_window_mgr_unregister_header (mgr, header);
5066
5067         g_object_unref (parts);
5068 }
5069
5070 static void
5071 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5072                                                      ModestMainWindow *win)
5073 {
5074         GtkWidget *header_view;
5075         TnyList *header_list;
5076         TnyHeader *header;
5077         TnyHeaderFlags flags;
5078         ModestWindow *msg_view_window =  NULL;
5079         gboolean found;
5080
5081         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5082
5083         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5084                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5085
5086         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5087         if (!header_list) {
5088                 g_warning ("%s: no header selected", __FUNCTION__);
5089                 return;
5090         }
5091         
5092         if (tny_list_get_length (header_list) == 1) {
5093                 TnyIterator *iter = tny_list_create_iterator (header_list);
5094                 header = TNY_HEADER (tny_iterator_get_current (iter));
5095                 g_object_unref (iter);
5096         } else
5097                 return;
5098         
5099         if (!header || !TNY_IS_HEADER(header)) {
5100                 g_warning ("%s: header is not valid", __FUNCTION__);
5101                 return;
5102         }
5103         
5104         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5105                                                           header, &msg_view_window);
5106         flags = tny_header_get_flags (header);
5107         if (!(flags & TNY_HEADER_FLAG_CACHED))
5108                 return;
5109         if (found) {
5110                 if (msg_view_window != NULL) 
5111                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5112                 else {
5113                         /* do nothing; uid was registered before, so window is probably on it's way */
5114                         g_warning ("debug: header %p has already been registered", header);
5115                 }
5116         } else {
5117                 ModestMailOperation *mail_op = NULL;
5118                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5119                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5120                                                                          modest_ui_actions_disk_operations_error_handler,
5121                                                                          NULL, NULL);
5122                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5123                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5124                 
5125                 g_object_unref (mail_op);
5126         }
5127         if (header)
5128                 g_object_unref (header);
5129         if (header_list)
5130                 g_object_unref (header_list);
5131 }
5132
5133 /*
5134  * Checks if we need a connection to do the transfer and if the user
5135  * wants to connect to complete it
5136  */
5137 void
5138 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5139                                        TnyFolderStore *src_folder,
5140                                        TnyList *headers,
5141                                        TnyFolder *dst_folder,
5142                                        gboolean delete_originals,
5143                                        gboolean *need_connection,
5144                                        gboolean *do_xfer)
5145 {
5146         TnyAccount *src_account;
5147         gint uncached_msgs = 0;
5148
5149         uncached_msgs = header_list_count_uncached_msgs (headers);
5150
5151         /* We don't need any further check if
5152          *
5153          * 1- the source folder is local OR
5154          * 2- the device is already online
5155          */
5156         if (!modest_tny_folder_store_is_remote (src_folder) ||
5157             tny_device_is_online (modest_runtime_get_device())) {
5158                 *need_connection = FALSE;
5159                 *do_xfer = TRUE;
5160                 return;
5161         }
5162
5163         /* We must ask for a connection when
5164          *
5165          *   - the message(s) is not already cached   OR 
5166          *   - the message(s) is cached but the leave_on_server setting
5167          * is FALSE (because we need to sync the source folder to
5168          * delete the message from the server (for IMAP we could do it
5169          * offline, it'll take place the next time we get a
5170          * connection)
5171          */
5172         src_account = get_account_from_folder_store (src_folder);
5173         if (uncached_msgs > 0) {
5174                 guint num_headers;
5175                 const gchar *msg;
5176
5177                 *need_connection = TRUE;
5178                 num_headers = tny_list_get_length (headers);
5179                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5180
5181                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5182                     GTK_RESPONSE_CANCEL) {
5183                         *do_xfer = FALSE;
5184                 } else {
5185                         *do_xfer = TRUE;
5186                 }
5187         } else {
5188                 /* The transfer is possible and the user wants to */
5189                 *do_xfer = TRUE;
5190
5191                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5192                         const gchar *account_name;
5193                         gboolean leave_on_server;
5194                         
5195                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5196                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5197                                                                                   account_name);
5198                         
5199                         if (leave_on_server == TRUE) {
5200                                 *need_connection = FALSE;
5201                         } else {
5202                                 *need_connection = TRUE;
5203                         }
5204                 } else {
5205                         *need_connection = FALSE;
5206                 }
5207         }
5208
5209         /* Frees */
5210         g_object_unref (src_account);
5211 }
5212
5213 static void
5214 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5215                              gpointer user_data)
5216 {
5217         ModestWindow *main_window = NULL;
5218
5219         /* Disable next automatic folder selection */
5220         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5221                                                          FALSE); /* don't create */
5222         if (main_window) {
5223                 GObject *win = modest_mail_operation_get_source (mail_op);
5224                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5225                                                         _("mail_in_ui_folder_move_target_error"), 
5226                                                         FALSE);
5227                 if (win)
5228                         g_object_unref (win);
5229         }
5230         move_to_helper_destroyer (user_data);
5231 }
5232
5233 typedef struct {
5234         TnyFolderStore *dst_folder;
5235         TnyList *headers;
5236 } XferMsgsHelper;
5237
5238 /**
5239  * Utility function that transfer messages from both the main window
5240  * and the msg view window when using the "Move to" dialog
5241  */
5242 static void
5243 xfer_messages_performer  (gboolean canceled, 
5244                           GError *err,
5245                           GtkWindow *parent_window, 
5246                           TnyAccount *account, 
5247                           gpointer user_data)
5248 {
5249         ModestWindow *win = MODEST_WINDOW (parent_window);
5250         TnyAccount *dst_account = NULL;
5251         gboolean dst_forbids_message_add = FALSE;
5252         XferMsgsHelper *helper;
5253         MoveToHelper *movehelper;
5254         ModestMailOperation *mail_op;
5255
5256         helper = (XferMsgsHelper *) user_data;
5257
5258         if (canceled || err) {
5259                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5260                         /* Show the proper error message */
5261                         modest_ui_actions_on_account_connection_error (parent_window, account);
5262                 }
5263                 goto end;
5264         }
5265
5266         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5267
5268         /* tinymail will return NULL for local folders it seems */
5269         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5270                                                                                   modest_tny_account_get_protocol_type (dst_account),
5271                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5272         g_object_unref (dst_account);
5273
5274         if (dst_forbids_message_add) {
5275                 modest_platform_information_banner (GTK_WIDGET (win),
5276                                                     NULL,
5277                                                     ngettext("mail_in_ui_folder_move_target_error",
5278                                                              "mail_in_ui_folder_move_targets_error",
5279                                                              tny_list_get_length (helper->headers)));
5280                 goto end;
5281         }
5282
5283         movehelper = g_new0 (MoveToHelper, 1);
5284         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5285                                                                _CS("ckct_nw_pasting"));
5286         if (movehelper->banner != NULL)  {
5287                 g_object_ref (movehelper->banner);
5288                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5289         }
5290
5291         if (MODEST_IS_MAIN_WINDOW (win)) {
5292                 GtkWidget *header_view = 
5293                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5294                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5295                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5296         }
5297
5298         /* Perform the mail operation */
5299         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5300                                                                  xfer_messages_error_handler,
5301                                                                  movehelper, NULL);
5302         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5303                                          mail_op);
5304
5305         modest_mail_operation_xfer_msgs (mail_op, 
5306                                          helper->headers,
5307                                          TNY_FOLDER (helper->dst_folder),
5308                                          TRUE,
5309                                          msgs_move_to_cb,
5310                                          movehelper);
5311
5312         g_object_unref (G_OBJECT (mail_op));
5313  end:
5314         g_object_unref (helper->dst_folder);
5315         g_object_unref (helper->headers);
5316         g_slice_free (XferMsgsHelper, helper);
5317 }
5318
5319 typedef struct {
5320         TnyFolder *src_folder;
5321         TnyFolderStore *dst_folder;
5322         gboolean delete_original;
5323         GtkWidget *folder_view;
5324 } MoveFolderInfo;
5325
5326 static void
5327 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5328                 TnyAccount *account, gpointer user_data)
5329 {
5330         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5331         GtkTreeSelection *sel;
5332         ModestMailOperation *mail_op = NULL;
5333         
5334         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5335                 g_object_unref (G_OBJECT (info->src_folder));
5336                 g_object_unref (G_OBJECT (info->dst_folder));
5337                 g_free (info);
5338                 return;
5339         }
5340         
5341         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5342         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5343                         _CS("ckct_nw_pasting"));
5344         if (helper->banner != NULL)  {
5345                 g_object_ref (helper->banner);
5346                 gtk_widget_show (GTK_WIDGET(helper->banner));
5347         }
5348         /* Clean folder on header view before moving it */
5349         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5350         gtk_tree_selection_unselect_all (sel);
5351
5352         /* Let gtk events run. We need that the folder
5353            view frees its reference to the source
5354            folder *before* issuing the mail operation
5355            so we need the signal handler of selection
5356            changed to happen before the mail
5357            operation 
5358         while (gtk_events_pending ())
5359                 gtk_main_iteration ();   */
5360
5361         mail_op =
5362                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5363                                 modest_ui_actions_move_folder_error_handler,
5364                                 info->src_folder, NULL);
5365         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5366                         mail_op);
5367
5368         /* Select *after* the changes */
5369         /* TODO: this function hangs UI after transfer */ 
5370         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5371         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5372
5373         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5374                                           TNY_FOLDER (info->dst_folder), TRUE);
5375         modest_mail_operation_xfer_folder (mail_op,
5376                         TNY_FOLDER (info->src_folder),
5377                         info->dst_folder,
5378                         info->delete_original, 
5379                         folder_move_to_cb, 
5380                         helper);
5381         g_object_unref (G_OBJECT (info->src_folder));
5382
5383         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5384         /* } */
5385         
5386         /* Unref mail operation */
5387         g_object_unref (G_OBJECT (mail_op));
5388         g_object_unref (G_OBJECT (info->dst_folder));
5389         g_free (user_data);
5390 }
5391
5392 static TnyAccount *
5393 get_account_from_folder_store (TnyFolderStore *folder_store) 
5394 {
5395         if (TNY_IS_ACCOUNT (folder_store))
5396                 return g_object_ref (folder_store);
5397         else
5398                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5399 }
5400
5401 /*
5402  * UI handler for the "Move to" action when invoked from the
5403  * ModestMainWindow
5404  */
5405 static void 
5406 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5407                                           GtkWidget *folder_view,
5408                                           TnyFolderStore *dst_folder,
5409                                           ModestMainWindow *win)
5410 {
5411         ModestHeaderView *header_view = NULL;
5412         TnyFolderStore *src_folder = NULL;
5413
5414         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5415
5416         /* Get the source folder */
5417         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5418
5419         /* Get header view */
5420         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5421
5422         /* Get folder or messages to transfer */
5423         if (gtk_widget_is_focus (folder_view)) {
5424                 gboolean do_xfer = TRUE;
5425
5426                 /* Allow only to transfer folders to the local root folder */
5427                 if (TNY_IS_ACCOUNT (dst_folder) && 
5428                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5429                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5430                         do_xfer = FALSE;
5431                 } else if (!TNY_IS_FOLDER (src_folder)) {
5432                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5433                         do_xfer = FALSE;
5434                 }
5435
5436                 if (do_xfer) {                  
5437                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5438                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5439
5440                         info->src_folder = g_object_ref (src_folder);
5441                         info->dst_folder = g_object_ref (dst_folder);
5442                         info->delete_original = TRUE;
5443                         info->folder_view = folder_view;
5444
5445                         connect_info->callback = on_move_folder_cb;
5446                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5447                         connect_info->data = info;
5448
5449                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5450                                                                    TNY_FOLDER_STORE (src_folder), 
5451                                                                    connect_info);
5452                 }
5453         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5454                 TnyList *headers;
5455
5456                 headers = modest_header_view_get_selected_headers(header_view);
5457
5458                 /* Transfer the messages */
5459                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5460                                                             headers, TNY_FOLDER (dst_folder));
5461
5462                 g_object_unref (headers);
5463         }
5464
5465         /* Frees */
5466         g_object_unref (src_folder);
5467 }
5468
5469
5470 void
5471 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5472                                             TnyFolder *src_folder,
5473                                             TnyList *headers,
5474                                             TnyFolder *dst_folder)
5475 {
5476         gboolean need_connection = TRUE;
5477         gboolean do_xfer = TRUE;
5478         XferMsgsHelper *helper;
5479
5480         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5481         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5482         g_return_if_fail (TNY_IS_LIST (headers));
5483         
5484         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5485                                                headers, TNY_FOLDER (dst_folder),
5486                                                TRUE, &need_connection, 
5487                                                &do_xfer);
5488
5489         /* If we don't want to transfer just return */
5490         if (!do_xfer)
5491                 return;
5492
5493         /* Create the helper */
5494         helper = g_slice_new (XferMsgsHelper);
5495         helper->dst_folder = g_object_ref (dst_folder);
5496         helper->headers = g_object_ref (headers);
5497
5498         if (need_connection) {
5499                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5500                 connect_info->callback = xfer_messages_performer;
5501                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5502                 connect_info->data = helper;
5503                 
5504                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5505                                                            TNY_FOLDER_STORE (src_folder), 
5506                                                            connect_info);
5507         } else {
5508                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5509                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5510                                          src_account, helper);
5511                 g_object_unref (src_account);
5512         }
5513 }
5514
5515 /*
5516  * UI handler for the "Move to" action when invoked from the
5517  * ModestMsgViewWindow
5518  */
5519 static void 
5520 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5521                                               TnyFolderStore *dst_folder,
5522                                               ModestMsgViewWindow *win)
5523 {
5524         TnyList *headers = NULL;
5525         TnyHeader *header = NULL;
5526         TnyFolder *src_folder = NULL;
5527
5528         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5529
5530         /* Create header list */
5531         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5532         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5533         headers = tny_simple_list_new ();
5534         tny_list_append (headers, G_OBJECT (header));
5535
5536         /* Transfer the messages */
5537         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5538                                                     TNY_FOLDER (dst_folder));
5539
5540         /* Frees */
5541         g_object_unref (src_folder);
5542         g_object_unref (header);
5543         g_object_unref (headers);
5544 }
5545
5546 void 
5547 modest_ui_actions_on_move_to (GtkAction *action, 
5548                               ModestWindow *win)
5549 {
5550         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5551         gint result = 0;
5552         TnyFolderStore *dst_folder = NULL;
5553         ModestMainWindow *main_window;
5554
5555         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5556                           MODEST_IS_MSG_VIEW_WINDOW (win));
5557
5558         /* Get the main window if exists */
5559         if (MODEST_IS_MAIN_WINDOW (win))
5560                 main_window = MODEST_MAIN_WINDOW (win);
5561         else
5562                 main_window = 
5563                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5564                                                                                FALSE)); /* don't create */
5565
5566         /* Get the folder view widget if exists */
5567         if (main_window)
5568                 folder_view = modest_main_window_get_child_widget (main_window,
5569                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5570         else
5571                 folder_view = NULL;
5572
5573         /* Create and run the dialog */
5574         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5575         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5576         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) win);
5577         result = gtk_dialog_run (GTK_DIALOG(dialog));
5578         g_object_ref (tree_view);
5579         gtk_widget_destroy (dialog);
5580
5581         if (result != GTK_RESPONSE_ACCEPT)
5582                 return;
5583
5584         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5585         /* Do window specific stuff */
5586         if (MODEST_IS_MAIN_WINDOW (win)) {
5587                 modest_ui_actions_on_main_window_move_to (action,
5588                                 folder_view,
5589                                 dst_folder,
5590                                 MODEST_MAIN_WINDOW (win));
5591         } else {
5592                 modest_ui_actions_on_msg_view_window_move_to (action,
5593                                 dst_folder,
5594                                 MODEST_MSG_VIEW_WINDOW (win));
5595         }
5596
5597         if (dst_folder)
5598                 g_object_unref (dst_folder);
5599 }
5600
5601 /*
5602  * Calls #HeadersFunc for each header already selected in the main
5603  * window or the message currently being shown in the msg view window
5604  */
5605 static void
5606 do_headers_action (ModestWindow *win, 
5607                    HeadersFunc func,
5608                    gpointer user_data)
5609 {
5610         TnyList *headers_list = NULL;
5611         TnyIterator *iter = NULL;
5612         TnyHeader *header = NULL;
5613         TnyFolder *folder = NULL;
5614
5615         /* Get headers */
5616         headers_list = get_selected_headers (win);
5617         if (!headers_list)
5618                 return;
5619
5620         /* Get the folder */
5621         iter = tny_list_create_iterator (headers_list);
5622         header = TNY_HEADER (tny_iterator_get_current (iter));
5623         if (header) {
5624                 folder = tny_header_get_folder (header);
5625                 g_object_unref (header);
5626         }
5627
5628         /* Call the function for each header */
5629         while (!tny_iterator_is_done (iter)) {
5630                 header = TNY_HEADER (tny_iterator_get_current (iter));
5631                 func (header, win, user_data);
5632                 g_object_unref (header);
5633                 tny_iterator_next (iter);
5634         }
5635
5636         /* Trick: do a poke status in order to speed up the signaling
5637            of observers */
5638         tny_folder_poke_status (folder);
5639
5640         /* Frees */
5641         g_object_unref (folder);
5642         g_object_unref (iter);
5643         g_object_unref (headers_list);
5644 }
5645
5646 void 
5647 modest_ui_actions_view_attachment (GtkAction *action,
5648                                    ModestWindow *window)
5649 {
5650         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5651                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5652         } else {
5653                 /* not supported window for this action */
5654                 g_return_if_reached ();
5655         }
5656 }
5657
5658 void
5659 modest_ui_actions_save_attachments (GtkAction *action,
5660                                     ModestWindow *window)
5661 {
5662         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5663
5664                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5665                         return;
5666
5667                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5668         } else {
5669                 /* not supported window for this action */
5670                 g_return_if_reached ();
5671         }
5672 }
5673
5674 void
5675 modest_ui_actions_remove_attachments (GtkAction *action,
5676                                       ModestWindow *window)
5677 {
5678         if (MODEST_IS_MAIN_WINDOW (window)) {
5679                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5680         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5681                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5682         } else {
5683                 /* not supported window for this action */
5684                 g_return_if_reached ();
5685         }
5686 }
5687
5688 void 
5689 modest_ui_actions_on_settings (GtkAction *action, 
5690                                ModestWindow *win)
5691 {
5692         GtkWidget *dialog;
5693
5694         dialog = modest_platform_get_global_settings_dialog ();
5695         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5696         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5697         gtk_widget_show_all (dialog);
5698
5699         gtk_dialog_run (GTK_DIALOG (dialog));
5700
5701         gtk_widget_destroy (dialog);
5702 }
5703
5704 void 
5705 modest_ui_actions_on_help (GtkAction *action, 
5706                            GtkWindow *win)
5707 {
5708         /* Help app is not available at all in fremantle */
5709 #ifndef MODEST_TOOLKIT_HILDON2
5710         const gchar *help_id;
5711
5712         g_return_if_fail (win && GTK_IS_WINDOW(win));
5713         
5714         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5715
5716         if (help_id)
5717                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5718 #endif
5719 }
5720
5721 void 
5722 modest_ui_actions_on_csm_help (GtkAction *action, 
5723                                GtkWindow *win)
5724 {
5725         /* Help app is not available at all in fremantle */
5726 #ifndef MODEST_TOOLKIT_HILDON2
5727
5728         const gchar* help_id = NULL;
5729         GtkWidget *folder_view;
5730         TnyFolderStore *folder_store;
5731
5732         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5733
5734         /* Get selected folder */
5735         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5736                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5737         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5738
5739         /* Switch help_id */
5740         if (folder_store && TNY_IS_FOLDER (folder_store))
5741                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5742
5743         if (folder_store)
5744                 g_object_unref (folder_store);
5745
5746         if (help_id)
5747                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5748         else
5749                 modest_ui_actions_on_help (action, win);
5750 #endif
5751 }
5752
5753 static void     
5754 retrieve_contents_cb (ModestMailOperation *mail_op, 
5755                       TnyHeader *header, 
5756                       gboolean canceled,
5757                       TnyMsg *msg,
5758                       GError *err,
5759                       gpointer user_data)
5760 {
5761         /* We only need this callback to show an error in case of
5762            memory low condition */
5763         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5764 }
5765
5766 static void
5767 retrieve_msg_contents_performer (gboolean canceled, 
5768                                  GError *err,
5769                                  GtkWindow *parent_window, 
5770                                  TnyAccount *account, 
5771                                  gpointer user_data)
5772 {
5773         ModestMailOperation *mail_op;
5774         TnyList *headers = TNY_LIST (user_data);
5775
5776         if (err || canceled) {
5777                 check_memory_full_error ((GtkWidget *) parent_window, err);
5778                 goto out;
5779         }
5780
5781         /* Create mail operation */
5782         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5783                                                                  modest_ui_actions_disk_operations_error_handler, 
5784                                                                  NULL, NULL);
5785         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5786         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5787
5788         /* Frees */
5789         g_object_unref (mail_op);
5790  out:
5791         g_object_unref (headers);
5792         g_object_unref (account);
5793 }
5794
5795 void 
5796 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5797                                             ModestWindow *window)
5798 {
5799         TnyList *headers = NULL;
5800         TnyAccount *account = NULL;
5801         TnyIterator *iter = NULL;
5802         TnyHeader *header = NULL;
5803         TnyFolder *folder = NULL;
5804
5805         /* Get headers */
5806         headers = get_selected_headers (window);
5807         if (!headers)
5808                 return;
5809
5810         /* Pick the account */
5811         iter = tny_list_create_iterator (headers);
5812         header = TNY_HEADER (tny_iterator_get_current (iter));
5813         folder = tny_header_get_folder (header);
5814         account = tny_folder_get_account (folder);
5815         g_object_unref (folder);
5816         g_object_unref (header);
5817         g_object_unref (iter);
5818
5819         /* Connect and perform the message retrieval */
5820         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5821                                              g_object_ref (account), 
5822                                              retrieve_msg_contents_performer, 
5823                                              g_object_ref (headers));
5824
5825         /* Frees */
5826         g_object_unref (account);
5827         g_object_unref (headers);
5828 }
5829
5830 void
5831 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5832 {
5833         g_return_if_fail (MODEST_IS_WINDOW (window));
5834
5835         /* Update dimmed */
5836         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5837 }
5838
5839 void
5840 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5841 {
5842         g_return_if_fail (MODEST_IS_WINDOW (window));
5843
5844         /* Update dimmed */
5845         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5846 }
5847
5848 void
5849 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5850                                           ModestWindow *window)
5851 {
5852         g_return_if_fail (MODEST_IS_WINDOW (window));
5853         
5854         /* Update dimmed */
5855         modest_ui_actions_check_menu_dimming_rules (window);
5856 }
5857
5858 void
5859 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5860                                           ModestWindow *window)
5861 {
5862         g_return_if_fail (MODEST_IS_WINDOW (window));
5863
5864         /* Update dimmed */
5865         modest_ui_actions_check_menu_dimming_rules (window);
5866 }
5867
5868 void
5869 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5870                                           ModestWindow *window)
5871 {
5872         g_return_if_fail (MODEST_IS_WINDOW (window));
5873
5874         /* Update dimmed */
5875         modest_ui_actions_check_menu_dimming_rules (window);
5876 }
5877
5878 void
5879 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5880                                             ModestWindow *window)
5881 {
5882         g_return_if_fail (MODEST_IS_WINDOW (window));
5883
5884         /* Update dimmed */
5885         modest_ui_actions_check_menu_dimming_rules (window);
5886 }
5887
5888 void
5889 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5890                                           ModestWindow *window)
5891 {
5892         g_return_if_fail (MODEST_IS_WINDOW (window));
5893
5894         /* Update dimmed */
5895         modest_ui_actions_check_menu_dimming_rules (window);
5896 }
5897
5898 void
5899 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5900                                           ModestWindow *window)
5901 {
5902         g_return_if_fail (MODEST_IS_WINDOW (window));
5903
5904         /* Update dimmed */
5905         modest_ui_actions_check_menu_dimming_rules (window);
5906 }
5907
5908 void
5909 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5910                                                  ModestWindow *window)
5911 {
5912         g_return_if_fail (MODEST_IS_WINDOW (window));
5913
5914         /* Update dimmed */
5915         modest_ui_actions_check_menu_dimming_rules (window);
5916 }
5917
5918 void
5919 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5920                                                      ModestWindow *window)
5921 {
5922         g_return_if_fail (MODEST_IS_WINDOW (window));
5923
5924         /* Update dimmed */
5925         modest_ui_actions_check_menu_dimming_rules (window);
5926 }
5927
5928 void
5929 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5930                                                      ModestWindow *window)
5931 {
5932         g_return_if_fail (MODEST_IS_WINDOW (window));
5933
5934         /* Update dimmed */
5935         modest_ui_actions_check_menu_dimming_rules (window);
5936 }
5937
5938 void
5939 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5940 {
5941         g_return_if_fail (MODEST_IS_WINDOW (window));
5942
5943         /* we check for low-mem; in that case, show a warning, and don't allow
5944          * searching
5945          */
5946         if (modest_platform_check_memory_low (window, TRUE))
5947                 return;
5948         
5949         modest_platform_show_search_messages (GTK_WINDOW (window));
5950 }
5951
5952 void     
5953 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5954 {
5955         g_return_if_fail (MODEST_IS_WINDOW (win));
5956
5957
5958         /* we check for low-mem; in that case, show a warning, and don't allow
5959          * for the addressbook
5960          */
5961         if (modest_platform_check_memory_low (win, TRUE))
5962                 return;
5963
5964
5965         modest_platform_show_addressbook (GTK_WINDOW (win));
5966 }
5967
5968
5969 void
5970 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5971                                           ModestWindow *window)
5972 {
5973         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5974
5975         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5976 }
5977
5978 static void 
5979 on_send_receive_finished (ModestMailOperation  *mail_op, 
5980                            gpointer user_data)
5981 {
5982         GtkWidget *header_view, *folder_view;
5983         TnyFolderStore *folder_store;
5984         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5985
5986         /* Set send/receive operation finished */       
5987         modest_main_window_notify_send_receive_completed (main_win);
5988
5989         /* Don't refresh the current folder if there were any errors */
5990         if (modest_mail_operation_get_status (mail_op) !=
5991             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5992                 return;
5993         
5994         /* Refresh the current folder if we're viewing a window. We do
5995            this because the user won't be able to see the new mails in
5996            the selected folder after a Send&Receive because it only
5997            performs a poke_status, i.e, only the number of read/unread
5998            messages is updated, but the new headers are not
5999            downloaded */
6000         folder_view = modest_main_window_get_child_widget (main_win, 
6001                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6002         if (!folder_view)
6003                 return;
6004
6005         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6006         
6007         /* Do not need to refresh INBOX again because the
6008            update_account does it always automatically */
6009         if (folder_store && TNY_IS_FOLDER (folder_store) && 
6010             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6011                 ModestMailOperation *refresh_op;
6012
6013                 header_view = modest_main_window_get_child_widget (main_win,
6014                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6015                 
6016                 /* We do not need to set the contents style
6017                    because it hasn't changed. We also do not
6018                    need to save the widget status. Just force
6019                    a refresh */
6020                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6021                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6022                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6023                                                       folder_refreshed_cb, main_win);
6024                 g_object_unref (refresh_op);
6025         }
6026         
6027         if (folder_store)
6028                 g_object_unref (folder_store);
6029 }
6030
6031
6032 void 
6033 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
6034                                                 TnyHeader *header, 
6035                                                 TnyMsg *msg, 
6036                                                 GError *err, 
6037                                                 gpointer user_data)
6038 {
6039         const gchar* server_name = NULL;
6040         TnyTransportAccount *server_account;
6041         gchar *message = NULL;
6042
6043         /* Don't show anything if the user cancelled something or the
6044          * send receive request is not interactive. Authentication
6045          * errors are managed by the account store so no need to show
6046          * a dialog here again */
6047         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6048             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6049             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6050                 return;
6051
6052
6053         /* Get the server name: */
6054         server_account = 
6055                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
6056         if (server_account)
6057                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
6058         else
6059                 g_return_if_reached ();
6060
6061         /* Show the appropriate message text for the GError: */
6062         switch (err->code) {
6063         case TNY_SERVICE_ERROR_CONNECT:
6064                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6065                 break;
6066         case TNY_SERVICE_ERROR_SEND:
6067                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6068                 break;
6069         case TNY_SERVICE_ERROR_UNAVAILABLE:
6070                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6071                 break;
6072         default:
6073                 g_warning ("%s: unexpected ERROR %d",
6074                            __FUNCTION__, err->code);
6075                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6076                 break;  
6077         }
6078
6079         modest_platform_run_information_dialog (NULL, message, FALSE);
6080         g_free (message);
6081         g_object_unref (server_account);
6082 }
6083
6084 void
6085 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6086                                                 gchar *msg_id, 
6087                                                 guint status,
6088                                                 gpointer user_data)
6089 {
6090         ModestMainWindow *main_window = NULL;
6091         ModestWindowMgr *mgr = NULL;
6092         GtkWidget *folder_view = NULL, *header_view = NULL;
6093         TnyFolderStore *selected_folder = NULL;
6094         TnyFolderType folder_type;
6095
6096         mgr = modest_runtime_get_window_mgr ();
6097         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6098                                                                              FALSE));/* don't create */
6099         if (!main_window)
6100                 return;
6101
6102         /* Check if selected folder is OUTBOX */
6103         folder_view = modest_main_window_get_child_widget (main_window,
6104                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6105         header_view = modest_main_window_get_child_widget (main_window,
6106                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6107
6108         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6109         if (!TNY_IS_FOLDER (selected_folder)) 
6110                 goto frees;
6111
6112         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6113 #if GTK_CHECK_VERSION(2, 8, 0) 
6114         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6115         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6116                 GtkTreeViewColumn *tree_column;
6117
6118                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6119                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6120                 if (tree_column)
6121                         gtk_tree_view_column_queue_resize (tree_column);
6122         }
6123 #else
6124         gtk_widget_queue_draw (header_view);
6125 #endif          
6126
6127         /* Rerun dimming rules, because the message could become deletable for example */
6128         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6129                                                  MODEST_DIMMING_RULES_TOOLBAR);
6130         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6131                                                  MODEST_DIMMING_RULES_MENU);
6132         
6133         /* Free */
6134  frees:
6135         if (selected_folder != NULL)
6136                 g_object_unref (selected_folder);
6137 }
6138
6139 void 
6140 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6141                                                TnyAccount *account)
6142 {
6143         ModestProtocolType protocol_type;
6144         ModestProtocol *protocol;
6145         gchar *error_note = NULL;
6146         
6147         protocol_type = modest_tny_account_get_protocol_type (account);
6148         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6149                                                                   protocol_type);
6150
6151         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6152         if (error_note == NULL) {
6153                 g_warning ("%s: This should not be reached", __FUNCTION__);
6154         } else {
6155                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6156                 g_free (error_note);
6157         }
6158 }
6159
6160 gchar *
6161 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6162 {
6163         gchar *msg = NULL;
6164         gchar *subject;
6165         TnyFolderStore *folder = NULL;
6166         TnyAccount *account = NULL;
6167         ModestProtocolType proto;
6168         ModestProtocol *protocol;
6169         TnyHeader *header = NULL;
6170
6171         if (MODEST_IS_MAIN_WINDOW (win)) {
6172                 GtkWidget *header_view;
6173                 TnyList* headers = NULL;
6174                 TnyIterator *iter;
6175                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6176                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6177                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6178                 if (!headers || tny_list_get_length (headers) == 0) {
6179                         if (headers)
6180                                 g_object_unref (headers);
6181                         return NULL;
6182                 }
6183                 iter = tny_list_create_iterator (headers);
6184                 header = TNY_HEADER (tny_iterator_get_current (iter));
6185                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6186                 g_object_unref (iter);
6187                 g_object_unref (headers);
6188         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6189                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6190                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6191         }
6192
6193         /* Get the account type */
6194         account = tny_folder_get_account (TNY_FOLDER (folder));
6195         proto = modest_tny_account_get_protocol_type (account);
6196         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6197                                                                   proto);
6198
6199         subject = tny_header_dup_subject (header);
6200         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6201         if (subject)
6202                 g_free (subject);
6203         if (msg == NULL) {
6204                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6205         }
6206
6207         /* Frees */
6208         g_object_unref (account);
6209         g_object_unref (folder);
6210         g_object_unref (header);
6211
6212         return msg;
6213 }
6214
6215 gboolean
6216 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6217                                      const gchar *account_name,
6218                                      const gchar *account_title)
6219 {
6220         ModestAccountMgr *account_mgr;
6221         gchar *txt = NULL;
6222         gint response;
6223         ModestProtocol *protocol;
6224         gboolean removed = FALSE;
6225
6226         g_return_val_if_fail (account_name, FALSE);
6227         g_return_val_if_fail (account_title, FALSE);
6228
6229         account_mgr = modest_runtime_get_account_mgr();
6230
6231         /* The warning text depends on the account type: */
6232         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6233                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6234                                                                                                          account_name));
6235         txt = modest_protocol_get_translation (protocol,
6236                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6237                                                account_title);
6238         if (txt == NULL)
6239                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6240
6241         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6242         g_free (txt);
6243         txt = NULL;
6244
6245         if (response == GTK_RESPONSE_OK) {
6246                 /* Remove account. If it succeeds then it also removes
6247                    the account from the ModestAccountView: */
6248                 gboolean is_default = FALSE;
6249                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6250                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6251                         is_default = TRUE;
6252                 g_free (default_account_name);
6253
6254                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6255                 if (!removed)
6256                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6257         }
6258         return removed;
6259 }