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