* Changed the update_account_thread it now refreshes the INBOX and pokes the other...
[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
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.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
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         ModestMailOperation *mail_op;
108         TnyFolder *folder;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
144                                                    ModestMailOperationState *state,
145                                                    gpointer user_data);
146
147 static gint header_list_count_uncached_msgs (TnyList *header_list);
148 static gboolean connect_to_get_msg (
149                                                 GtkWindow *win,
150                                                 gint num_of_uncached_msgs);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200 /* Show the account creation wizard dialog.
201  * returns: TRUE if an account was created. FALSE if the user cancelled.
202  */
203 gboolean
204 modest_run_account_setup_wizard (ModestWindow *win)
205 {
206         gboolean result = FALSE;
207         GtkDialog *wizard;
208         
209         wizard = modest_window_mgr_get_easysetup_dialog
210                 (modest_runtime_get_window_mgr());
211         if (wizard) {
212                 /* old wizard is active already; present it and
213                  * act as if the user cancelled the non-existing
214                  * new one
215                  */
216                 printf ("wizard already active\n");
217                 return FALSE;
218         } else {
219                 /* there is no such wizard yet */
220                 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
221                 modest_window_mgr_set_easysetup_dialog
222                         (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
223         } 
224
225         
226         /* always present a main window in the background 
227          * we do it here, so we cannot end up with to wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win) 
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
231
232         /* make sure the mainwindow is visible */
233         gtk_widget_show_all (GTK_WIDGET(win));
234         gtk_window_present (GTK_WINDOW(win));
235
236         
237         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
238
239         /* Don't make this a modal window, because secondary windows will then 
240          * be unusable, freezing the UI: */
241         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
242         
243         gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
244         if (dialog_response == GTK_RESPONSE_CANCEL)
245                 result = FALSE;
246         else {
247                 /* Check whether an account was created: */
248                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
249         }
250         
251         gtk_widget_destroy (GTK_WIDGET (wizard));
252
253         /* clear it from the window mgr */
254         modest_window_mgr_set_easysetup_dialog
255                 (modest_runtime_get_window_mgr(), NULL);
256         
257         return result;
258 }
259
260
261 void   
262 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
263 {
264         GtkWidget *about;
265         const gchar *authors[] = {
266                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
267                 NULL
268         };
269         about = gtk_about_dialog_new ();
270         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
271         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
272         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
273                                         _("Copyright (c) 2006, Nokia Corporation\n"
274                                           "All rights reserved."));
275         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
276                                        _("a modest e-mail client\n\n"
277                                          "design and implementation: Dirk-Jan C. Binnema\n"
278                                          "contributions from the fine people at KC and Ig\n"
279                                          "uses the tinymail email framework written by Philip van Hoof"));
280         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
281         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
282         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
283         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
284         
285         gtk_dialog_run (GTK_DIALOG (about));
286         gtk_widget_destroy(about);
287 }
288
289 /*
290  * Gets the list of currently selected messages. If the win is the
291  * main window, then it returns a newly allocated list of the headers
292  * selected in the header view. If win is the msg view window, then
293  * the value returned is a list with just a single header.
294  *
295  * The caller of this funcion must free the list.
296  */
297 static TnyList *
298 get_selected_headers (ModestWindow *win)
299 {
300         if (MODEST_IS_MAIN_WINDOW(win)) {
301                 GtkWidget *header_view;         
302                 
303                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
304                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
305                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
306                 
307         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
308                 /* for MsgViewWindows, we simply return a list with one element */
309                 TnyHeader *header;
310                 TnyList *list = NULL;
311                 
312                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
313                 if (header != NULL) {
314                         list = tny_simple_list_new ();
315                         tny_list_prepend (list, G_OBJECT(header));
316                         g_object_unref (G_OBJECT(header));
317                 }
318
319                 return list;
320
321         } else
322                 return NULL;
323 }
324
325 static void
326 headers_action_mark_as_read (TnyHeader *header,
327                              ModestWindow *win,
328                              gpointer user_data)
329 {
330         TnyHeaderFlags flags;
331
332         g_return_if_fail (TNY_IS_HEADER(header));
333
334         flags = tny_header_get_flags (header);
335         if (flags & TNY_HEADER_FLAG_SEEN) return;
336         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
337 }
338
339 static void
340 headers_action_mark_as_unread (TnyHeader *header,
341                                ModestWindow *win,
342                                gpointer user_data)
343 {
344         TnyHeaderFlags flags;
345
346         g_return_if_fail (TNY_IS_HEADER(header));
347
348         flags = tny_header_get_flags (header);
349         if (flags & TNY_HEADER_FLAG_SEEN)  {
350                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
351         }
352 }
353
354 /** A convenience method, because deleting a message is 
355  * otherwise complicated, and it's best to change it in one place 
356  * when we change it.
357  */
358 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
359 {
360         ModestMailOperation *mail_op = NULL;
361         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
362                 win ? G_OBJECT(win) : NULL);
363         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
364                                          mail_op);
365         
366         /* Always delete. TODO: Move to trash still not supported */
367         modest_mail_operation_remove_msg (mail_op, header, FALSE);
368         g_object_unref (G_OBJECT (mail_op));
369 }
370
371 /** A convenience method, because deleting a message is 
372  * otherwise complicated, and it's best to change it in one place 
373  * when we change it.
374  */
375 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
376 {
377         ModestMailOperation *mail_op = NULL;
378         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
379                 win ? G_OBJECT(win) : NULL);
380         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
381                                          mail_op);
382         
383         /* Always delete. TODO: Move to trash still not supported */
384         modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
385         g_object_unref (G_OBJECT (mail_op));
386 }
387
388 /* static void */
389 /* headers_action_delete (TnyHeader *header, */
390 /*                     ModestWindow *win, */
391 /*                     gpointer user_data) */
392 /* { */
393 /*      modest_do_message_delete (header, win); */
394
395 /* } */
396
397 /** After deleing a message that is currently visible in a window, 
398  * show the next message from the list, or close the window if there are no more messages.
399  **/
400 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
401 {
402         /* Close msg view window or select next */
403         if (modest_msg_view_window_last_message_selected (win) &&
404                 modest_msg_view_window_first_message_selected (win)) {
405                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
406         } else {
407                 if (!modest_msg_view_window_select_next_message (win)) {
408                         gboolean ret_value;
409                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
410                 }
411         }
412 }
413
414 void
415 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
416 {
417         TnyList *header_list = NULL;
418         TnyIterator *iter = NULL;
419         TnyHeader *header = NULL;
420         gchar *message = NULL;
421         gchar *desc = NULL;
422         gint response;
423         ModestWindowMgr *mgr;
424         GtkWidget *header_view = NULL;
425
426         g_return_if_fail (MODEST_IS_WINDOW(win));
427         
428         /* Check first if the header view has the focus */
429         if (MODEST_IS_MAIN_WINDOW (win)) {
430                 header_view = 
431                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
432                                                              MODEST_WIDGET_TYPE_HEADER_VIEW);
433                 if (!gtk_widget_is_focus (header_view))
434                         return;
435         }
436         
437         /* Get the headers, either from the header view (if win is the main window),
438          * or from the message view window: */
439         header_list = get_selected_headers (win);
440         if (!header_list) return;
441                         
442         /* Check if any of the headers are already opened, or in the process of being opened */
443         if (MODEST_IS_MAIN_WINDOW (win)) {
444                 gboolean found;
445                 iter = tny_list_create_iterator (header_list);
446                 found = FALSE;
447                 mgr = modest_runtime_get_window_mgr ();
448                 while (!tny_iterator_is_done (iter) && !found) {
449                         header = TNY_HEADER (tny_iterator_get_current (iter));
450                         if (header) {
451                                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
452                                 g_object_unref (header);
453                         }
454
455                         tny_iterator_next (iter);
456                 }
457                 g_object_unref (iter);
458
459                 if (found) {
460                         gchar *num, *msg;
461
462                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
463                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
464
465                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
466                         
467                         g_free (msg);
468                         g_free (num);
469                         g_object_unref (header_list);
470                         return;
471                 }
472         }
473
474         /* Select message */
475         if (tny_list_get_length(header_list) == 1) {
476                 iter = tny_list_create_iterator (header_list);
477                 header = TNY_HEADER (tny_iterator_get_current (iter));
478                 if (header) {
479                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
480                         g_object_unref (header);
481                 }
482
483                 g_object_unref (iter);
484         }
485         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
486                                            tny_list_get_length(header_list)), desc);
487
488         /* Confirmation dialog */
489         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
490                                                             message);
491         
492
493         if (response == GTK_RESPONSE_OK) {      
494                 ModestWindow *main_window = NULL;
495                 ModestWindowMgr *mgr = NULL;
496                 GtkTreeModel *model = NULL;
497                 GtkTreeSelection *sel = NULL;
498                 GList *sel_list = NULL, *tmp = NULL;
499                 GtkTreeRowReference *next_row_reference = NULL;
500                 GtkTreeRowReference *prev_row_reference = NULL;
501                 GtkTreePath *next_path = NULL;
502                 GtkTreePath *prev_path = NULL;
503                 GError *err = NULL;
504
505                 /* Find last selected row */                    
506                 if (MODEST_IS_MAIN_WINDOW (win)) {
507                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
508                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
509                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
510                         for (tmp=sel_list; tmp; tmp=tmp->next) {
511                                 if (tmp->next == NULL) {
512                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
513                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
514
515                                         gtk_tree_path_prev (prev_path);
516                                         gtk_tree_path_next (next_path);
517
518                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
519                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
520                                 }
521                         }
522                 }
523                 
524                 /* Disable window dimming management */
525                 modest_window_disable_dimming (MODEST_WINDOW(win));
526
527                 /* Remove each header. If it's a view window header_view == NULL */
528                 modest_do_messages_delete (header_list, win);
529                 
530                 /* Enable window dimming management */
531                 gtk_tree_selection_unselect_all (sel);
532                 modest_window_enable_dimming (MODEST_WINDOW(win));
533                 
534                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
535                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
536                         
537                         /* Get main window */
538                         mgr = modest_runtime_get_window_mgr ();
539                         main_window = modest_window_mgr_get_main_window (mgr);
540                 }
541                 else {                  
542                         /* Move cursor to next row */
543                         main_window = win; 
544
545                         /* Select next or previous row */
546                         if (gtk_tree_row_reference_valid (next_row_reference)) {
547 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
548                                 gtk_tree_selection_select_path (sel, next_path);
549                         }
550                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
551                                 gtk_tree_selection_select_path (sel, prev_path);
552                         }
553
554                         /* Free */
555                         if (next_row_reference != NULL) 
556                                 gtk_tree_row_reference_free (next_row_reference);
557                         if (next_path != NULL) 
558                                 gtk_tree_path_free (next_path);                         
559                         if (prev_row_reference != NULL) 
560                                 gtk_tree_row_reference_free (prev_row_reference);
561                         if (prev_path != NULL) 
562                                 gtk_tree_path_free (prev_path);                         
563                 }
564
565                 if (err != NULL) {
566                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
567                         g_error_free(err);
568                 }
569                 
570                 /* Update toolbar dimming state */
571                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
572
573                 /* Free */
574                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
575                 g_list_free (sel_list);
576         }
577
578         /* Free*/
579         g_free(message);
580         g_free(desc);
581         g_object_unref (header_list);
582 }
583
584
585
586
587 /* delete either message or folder, based on where we are */
588 void
589 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
590 {
591         g_return_if_fail (MODEST_IS_WINDOW(win));
592         
593         /* Check first if the header view has the focus */
594         if (MODEST_IS_MAIN_WINDOW (win)) {
595                 GtkWidget *w;
596                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
597                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
598                 if (gtk_widget_is_focus (w)) {
599                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
600                         return;
601                 }
602         }
603         modest_ui_actions_on_delete_message (action, win);
604 }
605
606
607
608 void
609 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
610 {       
611         ModestWindowMgr *mgr = NULL;
612         
613 #ifdef MODEST_PLATFORM_MAEMO
614         modest_osso_save_state();
615 #endif /* MODEST_PLATFORM_MAEMO */
616
617         g_debug ("closing down, clearing %d item(s) from operation queue",
618                  modest_mail_operation_queue_num_elements
619                  (modest_runtime_get_mail_operation_queue()));
620
621         /* cancel all outstanding operations */
622         modest_mail_operation_queue_cancel_all 
623                 (modest_runtime_get_mail_operation_queue());
624         
625         g_debug ("queue has been cleared");
626
627
628         /* Check if there are opened editing windows */ 
629         mgr = modest_runtime_get_window_mgr ();
630         modest_window_mgr_close_all_windows (mgr);
631
632         /* note: when modest-tny-account-store is finalized,
633            it will automatically set all network connections
634            to offline */
635
636 /*      gtk_main_quit (); */
637 }
638
639 void
640 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
641 {
642         gboolean ret_value;
643
644         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
645
646 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
647 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
648 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
649 /*              gboolean ret_value; */
650 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
651 /*      } else if (MODEST_IS_WINDOW (win)) { */
652 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
653 /*      } else { */
654 /*              g_return_if_reached (); */
655 /*      } */
656 }
657
658 void
659 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
660 {
661         GtkClipboard *clipboard = NULL;
662         gchar *selection = NULL;
663
664         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
665         selection = gtk_clipboard_wait_for_text (clipboard);
666
667         /* Question: why is the clipboard being used here? 
668          * It doesn't really make a lot of sense. */
669
670         if (selection)
671         {
672                 modest_address_book_add_address (selection);
673                 g_free (selection);
674         }
675 }
676
677 void
678 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
679 {
680         /* This is currently only implemented for Maemo */
681 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
682         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
683                 modest_run_account_setup_wizard (win);
684                 return;
685         } else  {
686                 /* Show the list of accounts: */
687                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
688                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
689                 
690                 /* Don't make this a modal window, because secondary windows will then 
691                  * be unusable, freezing the UI: */
692                 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
693                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
694         }
695 #else
696         GtkWidget *dialog, *label;
697         
698         /* Create the widgets */
699         
700         dialog = gtk_dialog_new_with_buttons ("Message",
701                                               GTK_WINDOW(win),
702                                               GTK_DIALOG_DESTROY_WITH_PARENT,
703                                               GTK_STOCK_OK,
704                                               GTK_RESPONSE_NONE,
705                                               NULL);
706         label = gtk_label_new ("Hello World!");
707         
708         /* Ensure that the dialog box is destroyed when the user responds. */
709         
710         g_signal_connect_swapped (dialog, "response", 
711                                   G_CALLBACK (gtk_widget_destroy),
712                                   dialog);
713         
714         /* Add the label, and show everything we've added to the dialog. */
715         
716         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
717                            label);
718         gtk_widget_show_all (dialog);
719 #endif /* MODEST_PLATFORM_MAEMO */
720 }
721
722 static void
723 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
724 {
725         /* Save any changes. */
726         modest_connection_specific_smtp_window_save_server_accounts (
727                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
728         gtk_widget_destroy (GTK_WIDGET (window));
729 }
730
731
732
733 void
734 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
735 {
736         /* This is currently only implemented for Maemo,
737          * because it requires an API (libconic) to detect different connection 
738          * possiblities.
739          */
740 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
741         
742         /* Create the window if necessary: */
743         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
744         modest_connection_specific_smtp_window_fill_with_connections (
745                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
746                 modest_runtime_get_account_mgr());
747
748         /* Show the window: */  
749         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
750         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
751         gtk_widget_show (specific_window);
752     
753         /* Save changes when the window is hidden: */
754         g_signal_connect (specific_window, "hide", 
755                 G_CALLBACK (on_smtp_servers_window_hide), win);
756 #endif /* MODEST_PLATFORM_MAEMO */
757 }
758
759 void
760 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
761 {
762         ModestWindow *msg_win = NULL;
763         TnyMsg *msg = NULL;
764         TnyFolder *folder = NULL;
765         gchar *account_name = NULL;
766         gchar *from_str = NULL;
767 /*      GError *err = NULL; */
768         TnyAccount *account = NULL;
769         ModestWindowMgr *mgr;
770         gchar *signature = NULL, *blank_and_signature = NULL;
771
772         /* if there are no accounts yet, just show the wizard */
773         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
774                         const gboolean created = modest_run_account_setup_wizard (win);
775                         if (!created)
776                                 return;
777         }
778         
779         account_name = g_strdup (modest_window_get_active_account (win));
780         if (!account_name)
781                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
782         if (!account_name) {
783                 g_printerr ("modest: no account found\n");
784                 goto cleanup;
785         }
786         
787         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
788                                                                        account_name,
789                                                                        TNY_ACCOUNT_TYPE_STORE);
790         if (!account) {
791                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
792                 goto cleanup;
793         }
794
795         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
796         if (!from_str) {
797                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
798                 goto cleanup;
799         }
800
801         gboolean use_signature = FALSE;
802         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
803
804         if (use_signature) {
805                 blank_and_signature = g_strconcat ("\n", signature, NULL);
806         } else {
807                 blank_and_signature = g_strdup ("");
808         }
809
810         g_free (signature);
811
812         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
813         if (!msg) {
814                 g_printerr ("modest: failed to create new msg\n");
815                 goto cleanup;
816         }
817         
818         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
819         if (!folder) {
820                 g_printerr ("modest: failed to find Drafts folder\n");
821                 goto cleanup;
822         }
823         
824         
825         /* Create and register edit window */
826         /* This is destroyed by TODO. */
827         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
828         mgr = modest_runtime_get_window_mgr ();
829         modest_window_mgr_register_window (mgr, msg_win);
830
831         if (win)
832                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
833                                               GTK_WINDOW (win));
834         gtk_widget_show_all (GTK_WIDGET (msg_win));
835
836 cleanup:
837         g_free (account_name);
838         g_free (from_str);
839         g_free (blank_and_signature);
840         if (msg_win)
841                 g_object_unref (msg_win);
842         if (account)
843                 g_object_unref (G_OBJECT(account));
844         if (msg)
845                 g_object_unref (G_OBJECT(msg));
846         if (folder)
847                 g_object_unref (G_OBJECT(folder));
848 }
849
850 gboolean 
851 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
852                                        TnyHeader *header,
853                                        TnyMsg *msg)
854 {
855         ModestMailOperationStatus status;
856
857         /* If there is no message or the operation was not successful */
858         status = modest_mail_operation_get_status (mail_op);
859         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
860
861                 /* Remove the header from the preregistered uids */
862                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
863                                                      header);
864
865                 return FALSE;
866         }
867
868         return TRUE;
869 }
870
871 static void
872 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
873 {
874         ModestWindowMgr *mgr = NULL;
875         ModestWindow *parent_win = NULL;
876         ModestWindow *win = NULL;
877         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
878         gchar *account = NULL;
879         TnyFolder *folder;
880         
881         /* Do nothing if there was any problem with the mail
882            operation. The error will be shown by the error_handler of
883            the mail operation */
884         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
885                 return;
886
887         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
888         folder = tny_header_get_folder (header);
889
890         /* Mark header as read */
891         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
892
893         /* Get account */
894         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
895         if (!account)
896                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
897         
898         /* Gets folder type (OUTBOX headers will be opened in edit window */
899         if (modest_tny_folder_is_local_folder (folder))
900                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
901
902         /* If the header is in the drafts folder then open the editor,
903            else the message view window */
904         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
905             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
906                 /* we cannot edit without a valid account... */
907                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
908                         const gboolean created = modest_run_account_setup_wizard(parent_win);
909                         if (!created)
910                                 goto cleanup;
911                 }
912                 win = modest_msg_edit_window_new (msg, account, TRUE);
913
914
915                 /* Show banner */
916                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
917
918         } else {
919                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
920                 
921                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
922                         GtkWidget *header_view;
923                         GtkTreeSelection *sel;
924                         GList *sel_list = NULL;
925                         GtkTreeModel *model;
926                         
927                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
928                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
929
930                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
931                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
932
933                         if (sel_list != NULL) {
934                                 GtkTreeRowReference *row_reference;
935
936                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
937                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
938                                 g_list_free (sel_list);
939                                 
940                                 win = modest_msg_view_window_new_with_header_model (
941                                                 msg, account, (const gchar*) uid,
942                                                 model, row_reference);
943                                 gtk_tree_row_reference_free (row_reference);
944                         } else {
945                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
946                         }
947                 } else {
948                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
949                 }
950                 g_free (uid);
951         }
952         
953         /* Register and show new window */
954         if (win != NULL) {
955                 mgr = modest_runtime_get_window_mgr ();
956                 modest_window_mgr_register_window (mgr, win);
957                 g_object_unref (win);
958                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
959                 gtk_widget_show_all (GTK_WIDGET(win));
960         }
961
962         /* Update toolbar dimming state */
963         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
964                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
965         }
966
967 cleanup:
968         /* Free */
969         g_free(account);
970         g_object_unref (parent_win);
971         g_object_unref (folder);
972 }
973
974 void
975 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
976                                                gpointer user_data)
977 {
978         const GError *error;
979         GObject *win = modest_mail_operation_get_source (mail_op);
980
981         error = modest_mail_operation_get_error (mail_op);
982         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
983  
984         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
985
986                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
987                                                         error->message);
988         } else {
989                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
990                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
991         }
992
993         if (win)
994                 g_object_unref (win);
995 }
996
997 /*
998  * This function is used by both modest_ui_actions_on_open and
999  * modest_ui_actions_on_header_activated. This way we always do the
1000  * same when trying to open messages.
1001  */
1002 static void
1003 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
1004 {
1005         ModestWindowMgr *mgr = NULL;
1006         TnyIterator *iter = NULL;
1007         ModestMailOperation *mail_op = NULL;
1008         TnyList *not_opened_headers = NULL;
1009         TnyHeaderFlags flags = 0;
1010                 
1011         g_return_if_fail (headers != NULL);
1012
1013         /* Check that only one message is selected for opening */
1014         if (tny_list_get_length (headers) != 1) {
1015                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1016                                                         _("mcen_ib_select_one_message"));
1017                 return;
1018         }
1019
1020
1021         /* Look if we already have a message view for each header. If
1022            true, then remove the header from the list of headers to
1023            open */
1024         mgr = modest_runtime_get_window_mgr ();
1025         iter = tny_list_create_iterator (headers);
1026         not_opened_headers = tny_simple_list_new ();
1027         
1028         while (!tny_iterator_is_done (iter)) {
1029
1030                 ModestWindow *window = NULL;
1031                 TnyHeader *header = NULL;
1032                 gboolean found = FALSE;
1033                 
1034                 header = TNY_HEADER (tny_iterator_get_current (iter));
1035                 if (header)
1036                         flags = tny_header_get_flags (header);
1037
1038                 window = NULL;
1039                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1040                 
1041                 /* Do not open again the message and present the
1042                    window to the user */
1043                 if (found) {
1044                         if (window)
1045                                 gtk_window_present (GTK_WINDOW (window));
1046                         else
1047                                 /* the header has been registered already, we don't do
1048                                  * anything but wait for the window to come up*/
1049                                 g_debug ("header %p already registered, waiting for window", header);
1050                 } else {
1051                         tny_list_append (not_opened_headers, G_OBJECT (header));
1052                 }
1053
1054                 if (header)
1055                         g_object_unref (header);
1056
1057                 tny_iterator_next (iter);
1058         }
1059         g_object_unref (iter);
1060         iter = NULL;
1061         
1062         /* If some messages would have to be downloaded, ask the user to 
1063          * make a connection. It's generally easier to do this here (in the mainloop) 
1064          * than later in a thread:
1065          */
1066         if (tny_list_get_length (not_opened_headers) > 0) {
1067                 TnyIterator *iter;
1068                 gboolean found = FALSE;
1069
1070                 iter = tny_list_create_iterator (not_opened_headers);
1071                 while (!tny_iterator_is_done (iter) && !found) {
1072                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1073                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1074                                 found = TRUE;
1075                         else
1076                                 tny_iterator_next (iter);
1077
1078                         g_object_unref (header);
1079                 }
1080                 g_object_unref (iter);
1081
1082                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1083                         g_object_unref (not_opened_headers);
1084                         return;                 
1085                 }
1086         }
1087         
1088         /* Register the headers before actually creating the windows: */
1089         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1090         while (!tny_iterator_is_done (iter_not_opened)) {
1091                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1092                 if (header) {
1093                         modest_window_mgr_register_header (mgr, header);
1094                         g_object_unref (header);
1095                 }
1096                 
1097                 tny_iterator_next (iter_not_opened);
1098         }
1099         g_object_unref (iter_not_opened);
1100         iter_not_opened = NULL;
1101         
1102         /* Open each message */
1103         if (tny_list_get_length (not_opened_headers) > 0) {
1104                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1105                                                                          G_OBJECT (win), 
1106                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1107                                                                          NULL);
1108                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1109                 if (tny_list_get_length (not_opened_headers) > 1) {
1110                         modest_mail_operation_get_msgs_full (mail_op, 
1111                                                              not_opened_headers, 
1112                                                              open_msg_cb, 
1113                                                              NULL, 
1114                                                              NULL);
1115                 } else {
1116                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1117                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1118                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1119                         g_object_unref (header);
1120                         g_object_unref (iter);
1121                 }
1122                 g_object_unref (mail_op);
1123         }
1124
1125         /* Clean */
1126         if (not_opened_headers != NULL)
1127                 g_object_unref (not_opened_headers);
1128 }
1129
1130 void
1131 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1132 {
1133         TnyList *headers;
1134
1135         /* Get headers */
1136         headers = get_selected_headers (win);
1137         if (!headers)
1138                 return;
1139
1140         /* Open them */
1141         _modest_ui_actions_open (headers, win);
1142
1143         g_object_unref(headers);
1144 }
1145
1146
1147 static void
1148 free_reply_forward_helper (gpointer data)
1149 {
1150         ReplyForwardHelper *helper;
1151
1152         helper = (ReplyForwardHelper *) data;
1153         g_free (helper->account_name);
1154         g_slice_free (ReplyForwardHelper, helper);
1155 }
1156
1157 static void
1158 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1159                   gpointer user_data)
1160 {
1161         TnyMsg *new_msg;
1162         ReplyForwardHelper *rf_helper;
1163         ModestWindow *msg_win = NULL;
1164         ModestEditType edit_type;
1165         gchar *from = NULL;
1166         TnyAccount *account = NULL;
1167         ModestWindowMgr *mgr = NULL;
1168         gchar *signature = NULL;
1169
1170         /* If there was any error. The mail operation could be NULL,
1171            this means that we already have the message downloaded and
1172            that we didn't do a mail operation to retrieve it */
1173         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1174                 return;
1175                         
1176         g_return_if_fail (user_data != NULL);
1177         rf_helper = (ReplyForwardHelper *) user_data;
1178
1179         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1180                                                    rf_helper->account_name);
1181         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1182                                          rf_helper->account_name,
1183                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1184                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1185                                                            rf_helper->account_name,
1186                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1187         }
1188
1189         /* Create reply mail */
1190         switch (rf_helper->action) {
1191         case ACTION_REPLY:
1192                 new_msg = 
1193                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1194                                                          rf_helper->reply_forward_type,
1195                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1196                 break;
1197         case ACTION_REPLY_TO_ALL:
1198                 new_msg = 
1199                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1200                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1201                 edit_type = MODEST_EDIT_TYPE_REPLY;
1202                 break;
1203         case ACTION_FORWARD:
1204                 new_msg = 
1205                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1206                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1207                 break;
1208         default:
1209                 g_return_if_reached ();
1210                 return;
1211         }
1212
1213         g_free (signature);
1214
1215         if (!new_msg) {
1216                 g_printerr ("modest: failed to create message\n");
1217                 goto cleanup;
1218         }
1219
1220         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1221                                                                        rf_helper->account_name,
1222                                                                        TNY_ACCOUNT_TYPE_STORE);
1223         if (!account) {
1224                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1225                 goto cleanup;
1226         }
1227
1228         /* Create and register the windows */
1229         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1230         mgr = modest_runtime_get_window_mgr ();
1231         modest_window_mgr_register_window (mgr, msg_win);
1232
1233         if (rf_helper->parent_window != NULL) {
1234                 gdouble parent_zoom;
1235
1236                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1237                 modest_window_set_zoom (msg_win, parent_zoom);
1238         }
1239
1240         /* Show edit window */
1241         gtk_widget_show_all (GTK_WIDGET (msg_win));
1242
1243 cleanup:
1244         if (msg_win)
1245                 g_object_unref (msg_win);
1246         if (new_msg)
1247                 g_object_unref (G_OBJECT (new_msg));
1248         if (account)
1249                 g_object_unref (G_OBJECT (account));
1250 /*      g_object_unref (msg); */
1251         free_reply_forward_helper (rf_helper);
1252 }
1253
1254 /* Checks a list of headers. If any of them are not currently
1255  * downloaded (CACHED) then returns TRUE else returns FALSE.
1256  */
1257 static gint
1258 header_list_count_uncached_msgs (TnyList *header_list)
1259 {
1260         TnyIterator *iter;
1261         gint uncached_messages = 0;
1262
1263         iter = tny_list_create_iterator (header_list);
1264         while (!tny_iterator_is_done (iter)) {
1265                 TnyHeader *header;
1266
1267                 header = TNY_HEADER (tny_iterator_get_current (iter));
1268                 if (header) {
1269                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1270                                 uncached_messages ++;
1271                         g_object_unref (header);
1272                 }
1273
1274                 tny_iterator_next (iter);
1275         }
1276         g_object_unref (iter);
1277
1278         return uncached_messages;
1279 }
1280
1281 /* Returns FALSE if the user does not want to download the
1282  * messages. Returns TRUE if the user allowed the download.
1283  */
1284 static gboolean
1285 connect_to_get_msg (GtkWindow *win,
1286                     gint num_of_uncached_msgs)
1287 {
1288         /* Allways download if we are online. */
1289         if (tny_device_is_online (modest_runtime_get_device ()))
1290                 return TRUE;
1291
1292         /* If offline, then ask for user permission to download the messages */
1293         GtkResponseType response;
1294         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1295                         ngettext("mcen_nc_get_msg",
1296                         "mcen_nc_get_msgs",
1297                         num_of_uncached_msgs));
1298         if (response == GTK_RESPONSE_CANCEL)
1299                 return FALSE;
1300
1301         return modest_platform_connect_and_wait(win, NULL);     
1302 }
1303
1304 /*
1305  * Common code for the reply and forward actions
1306  */
1307 static void
1308 reply_forward (ReplyForwardAction action, ModestWindow *win)
1309 {
1310         ModestMailOperation *mail_op = NULL;
1311         TnyList *header_list = NULL;
1312         ReplyForwardHelper *rf_helper = NULL;
1313         guint reply_forward_type;
1314         gboolean continue_download = TRUE;
1315         gboolean do_retrieve = TRUE;
1316         
1317         g_return_if_fail (MODEST_IS_WINDOW(win));
1318
1319         /* we need an account when editing */
1320         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1321                 const gboolean created = modest_run_account_setup_wizard (win);
1322                 if (!created)
1323                         return;
1324         }
1325         
1326         header_list = get_selected_headers (win);
1327         if (!header_list)
1328                 return;
1329
1330         reply_forward_type = 
1331                 modest_conf_get_int (modest_runtime_get_conf (),
1332                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1333                                      NULL);
1334
1335         /* check if we need to download msg before asking about it */
1336         do_retrieve = (action == ACTION_FORWARD) ||
1337                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1338
1339         if (do_retrieve){
1340                 gint num_of_unc_msgs;
1341                 /* check that the messages have been previously downloaded */
1342                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1343                 /* If there are any uncached message ask the user
1344                  * whether he/she wants to download them. */
1345                 if (num_of_unc_msgs)
1346                         continue_download = connect_to_get_msg (
1347                                                                 GTK_WINDOW (win),
1348                                                                 num_of_unc_msgs);
1349         }
1350
1351         if (!continue_download) {
1352                 g_object_unref (header_list);
1353                 return;
1354         }
1355         
1356         /* We assume that we can only select messages of the
1357            same folder and that we reply all of them from the
1358            same account. In fact the interface currently only
1359            allows single selection */
1360         
1361         /* Fill helpers */
1362         rf_helper = g_slice_new0 (ReplyForwardHelper);
1363         rf_helper->reply_forward_type = reply_forward_type;
1364         rf_helper->action = action;
1365         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1366         
1367         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1368                 rf_helper->parent_window = GTK_WIDGET (win);
1369         if (!rf_helper->account_name)
1370                 rf_helper->account_name =
1371                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1372
1373         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1374                 TnyMsg *msg;
1375                 TnyHeader *header;
1376                 /* Get header and message. Do not free them here, the
1377                    reply_forward_cb must do it */
1378                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1379                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1380                 if (!msg || !header) {
1381                         if (msg)
1382                                 g_object_unref (msg);
1383                         g_printerr ("modest: no message found\n");
1384                         return;
1385                 } else {
1386                         reply_forward_cb (NULL, header, msg, rf_helper);
1387                 }
1388                 if (header)
1389                         g_object_unref (header);
1390         } else {
1391                 TnyHeader *header;
1392                 TnyIterator *iter;
1393
1394                 /* Only reply/forward to one message */
1395                 iter = tny_list_create_iterator (header_list);
1396                 header = TNY_HEADER (tny_iterator_get_current (iter));
1397                 g_object_unref (iter);
1398
1399                 if (header) {
1400                         /* Retrieve messages */
1401                         if (do_retrieve) {
1402                                 mail_op = modest_mail_operation_new_with_error_handling (
1403                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1404                                         G_OBJECT(win),
1405                                         modest_ui_actions_get_msgs_full_error_handler, 
1406                                         NULL);
1407                                 modest_mail_operation_queue_add (
1408                                         modest_runtime_get_mail_operation_queue (), mail_op);
1409                                 
1410                                 modest_mail_operation_get_msg (mail_op,
1411                                                                header,
1412                                                                reply_forward_cb,
1413                                                                rf_helper);
1414                                 /* Clean */
1415                                 g_object_unref(mail_op);
1416                         } else {
1417                                 /* we put a ref here to prevent double unref as the reply
1418                                  * forward callback unrefs the header at its end */
1419                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1420                         }
1421
1422
1423                         g_object_unref (header);
1424                 }
1425
1426         }
1427
1428         /* Free */
1429         g_object_unref (header_list);
1430 }
1431
1432 void
1433 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1434 {
1435         g_return_if_fail (MODEST_IS_WINDOW(win));
1436
1437         reply_forward (ACTION_REPLY, win);
1438 }
1439
1440 void
1441 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1442 {
1443         g_return_if_fail (MODEST_IS_WINDOW(win));
1444
1445         reply_forward (ACTION_FORWARD, win);
1446 }
1447
1448 void
1449 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1450 {
1451         g_return_if_fail (MODEST_IS_WINDOW(win));
1452
1453         reply_forward (ACTION_REPLY_TO_ALL, win);
1454 }
1455
1456 void 
1457 modest_ui_actions_on_next (GtkAction *action, 
1458                            ModestWindow *window)
1459 {
1460         if (MODEST_IS_MAIN_WINDOW (window)) {
1461                 GtkWidget *header_view;
1462
1463                 header_view = modest_main_window_get_child_widget (
1464                                 MODEST_MAIN_WINDOW(window),
1465                                 MODEST_WIDGET_TYPE_HEADER_VIEW);
1466                 if (!header_view)
1467                         return;
1468         
1469                 modest_header_view_select_next (
1470                                 MODEST_HEADER_VIEW(header_view)); 
1471         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1472                 modest_msg_view_window_select_next_message (
1473                                 MODEST_MSG_VIEW_WINDOW (window));
1474         } else {
1475                 g_return_if_reached ();
1476         }
1477 }
1478
1479 void 
1480 modest_ui_actions_on_prev (GtkAction *action, 
1481                            ModestWindow *window)
1482 {
1483         g_return_if_fail (MODEST_IS_WINDOW(window));
1484
1485         if (MODEST_IS_MAIN_WINDOW (window)) {
1486                 GtkWidget *header_view;
1487                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1488                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1489                 if (!header_view)
1490                         return;
1491                 
1492                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1493         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1494                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1495         } else {
1496                 g_return_if_reached ();
1497         }
1498 }
1499
1500 void 
1501 modest_ui_actions_on_sort (GtkAction *action, 
1502                            ModestWindow *window)
1503 {
1504         g_return_if_fail (MODEST_IS_WINDOW(window));
1505
1506         if (MODEST_IS_MAIN_WINDOW (window)) {
1507                 GtkWidget *header_view;
1508                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1509                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1510                 if (!header_view) {
1511                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1512
1513                         return;
1514                 }
1515
1516                 /* Show sorting dialog */
1517                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1518         }
1519 }
1520
1521 static void
1522 new_messages_arrived (ModestMailOperation *self, 
1523                       TnyList *new_headers,
1524                       gpointer user_data)
1525 {
1526         ModestMainWindow *win = NULL;
1527         GtkWidget *folder_view = NULL;
1528         TnyFolderStore *folder = NULL;
1529         gboolean folder_empty = FALSE;
1530
1531         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1532         win = MODEST_MAIN_WINDOW (user_data);
1533
1534         /* Set contents style of headers view */
1535         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1536                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1537                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
1538                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1539                 
1540
1541                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1542                 
1543                 if (!folder_empty)
1544                         modest_main_window_set_contents_style (win,
1545                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1546         }       
1547
1548         /* Notify new messages have been downloaded */
1549         if (tny_list_get_length (new_headers) > 0) {
1550                 TnyIterator *iter = tny_list_create_iterator (new_headers);
1551                 do {
1552                         TnyHeader *header =  NULL;
1553
1554                         header = TNY_HEADER (tny_iterator_get_current (iter));
1555                         modest_platform_on_new_header_received (header);
1556                         g_object_unref (header);
1557
1558                         tny_iterator_next (iter);
1559                 } while (!tny_iterator_is_done (iter));
1560                 g_object_unref (iter);
1561         }
1562 }
1563
1564 /*
1565  * This function performs the send & receive required actions. The
1566  * window is used to create the mail operation. Typically it should
1567  * always be the main window, but we pass it as argument in order to
1568  * be more flexible.
1569  */
1570 void
1571 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1572 {
1573         gchar *acc_name = NULL;
1574         ModestMailOperation *mail_op;
1575
1576         /* If no account name was provided then get the current account, and if
1577            there is no current account then pick the default one: */
1578         if (!account_name) {
1579                 acc_name = g_strdup (modest_window_get_active_account(win));
1580                 if (!acc_name)
1581                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1582                 if (!acc_name) {
1583                         g_printerr ("modest: cannot get default account\n");
1584                         return;
1585                 }
1586         } else {
1587                 acc_name = g_strdup (account_name);
1588         }
1589
1590         /* Set send/receive operation in progress */    
1591         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1592
1593         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1594                                                                  G_OBJECT (win),
1595                                                                  modest_ui_actions_send_receive_error_handler,
1596                                                                  NULL);
1597
1598         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1599                           G_CALLBACK (_on_send_receive_progress_changed), 
1600                           win);
1601
1602         /* Send & receive. */
1603         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1604         /* Receive and then send. The operation is tagged initially as
1605            a receive operation because the account update performs a
1606            receive and then a send. The operation changes its type
1607            internally, so the progress objects will receive the proper
1608            progress information */
1609         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1610         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1611         g_object_unref (G_OBJECT (mail_op));
1612         
1613         /* Free */
1614         g_free (acc_name);
1615 }
1616
1617
1618 static void
1619 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1620                                   ModestWindow *win)
1621 {
1622         TnyTransportAccount *transport_account;
1623         TnySendQueue *send_queue = NULL;
1624         GError *error = NULL;
1625
1626         /* Get transport account */
1627         transport_account =
1628                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1629                                       (modest_runtime_get_account_store(),
1630                                        account_name,
1631                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1632         if (!transport_account) {
1633                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1634                 goto frees;
1635         }
1636
1637         /* Get send queue*/
1638         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1639         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1640                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1641                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1642                              "modest: could not find send queue for account\n");
1643         } else {
1644                 /* Keeep messages in outbox folder */
1645                 tny_send_queue_cancel (send_queue, FALSE, &error);
1646         }       
1647
1648  frees:
1649         if (transport_account != NULL) 
1650                 g_object_unref (G_OBJECT (transport_account));
1651 }
1652
1653 static void
1654 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1655 {
1656         GSList *account_names, *iter;
1657
1658         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1659                                                           TRUE);
1660
1661         iter = account_names;
1662         while (iter) {                  
1663                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1664                 iter = g_slist_next (iter);
1665         }
1666
1667         modest_account_mgr_free_account_names (account_names);
1668         account_names = NULL;
1669 }
1670
1671 void
1672 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1673
1674 {
1675         /* Check if accounts exist */
1676         gboolean accounts_exist = 
1677                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1678         
1679         /* If not, allow the user to create an account before trying to send/receive. */
1680         if (!accounts_exist)
1681                 modest_ui_actions_on_accounts (NULL, win);
1682         
1683         /* Cancel all sending operaitons */     
1684         modest_ui_actions_cancel_send_all (win);
1685 }
1686
1687 /*
1688  * Refreshes all accounts. This function will be used by automatic
1689  * updates
1690  */
1691 void
1692 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1693 {
1694         GSList *account_names, *iter;
1695
1696         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1697                                                           TRUE);
1698
1699         iter = account_names;
1700         while (iter) {                  
1701                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1702                 iter = g_slist_next (iter);
1703         }
1704
1705         modest_account_mgr_free_account_names (account_names);
1706         account_names = NULL;
1707 }
1708
1709 void 
1710 modest_do_refresh_current_folder(ModestWindow *win)
1711 {
1712         /* Refresh currently selected folder. Note that if we only
1713            want to retreive the headers, then the refresh only will
1714            invoke a poke_status over all folders, i.e., only the
1715            total/unread count will be updated */
1716         if (MODEST_IS_MAIN_WINDOW (win)) {
1717                 GtkWidget *header_view, *folder_view;
1718                 TnyFolderStore *folder_store;
1719
1720                 /* Get folder and header view */
1721                 folder_view = 
1722                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1723                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1724                 if (!folder_view)
1725                         return;
1726
1727                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1728
1729                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1730                         header_view = 
1731                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1732                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1733                 
1734                         /* We do not need to set the contents style
1735                            because it hasn't changed. We also do not
1736                            need to save the widget status. Just force
1737                            a refresh */
1738                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1739                                                        TNY_FOLDER (folder_store),
1740                                                        folder_refreshed_cb,
1741                                                        MODEST_MAIN_WINDOW (win));
1742                 }
1743                 
1744                 if (folder_store)
1745                         g_object_unref (folder_store);
1746         }
1747 }
1748
1749
1750 /*
1751  * Handler of the click on Send&Receive button in the main toolbar
1752  */
1753 void
1754 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1755 {
1756         /* Check if accounts exist */
1757         gboolean accounts_exist = 
1758                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1759         
1760         /* If not, allow the user to create an account before trying to send/receive. */
1761         if (!accounts_exist)
1762                 modest_ui_actions_on_accounts (NULL, win);
1763
1764         modest_do_refresh_current_folder (win);
1765         
1766         /* Refresh the active account */
1767         modest_ui_actions_do_send_receive (NULL, win);
1768 }
1769
1770
1771 void
1772 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1773 {
1774         ModestConf *conf;
1775         GtkWidget *header_view;
1776         
1777         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1778
1779         header_view = modest_main_window_get_child_widget (main_window,
1780                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1781         if (!header_view)
1782                 return;
1783
1784         conf = modest_runtime_get_conf ();
1785         
1786         /* what is saved/restored is depending on the style; thus; we save with
1787          * old style, then update the style, and restore for this new style
1788          */
1789         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1790         
1791         if (modest_header_view_get_style
1792             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1793                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1794                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1795         else
1796                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1797                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1798
1799         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1800                                       MODEST_CONF_HEADER_VIEW_KEY);
1801 }
1802
1803
1804 void 
1805 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1806                                       TnyHeader *header,
1807                                       ModestMainWindow *main_window)
1808 {
1809         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1810         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1811         
1812         /* in the case the folder is empty, show the empty folder message and focus
1813          * folder view */
1814         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1815                 if (modest_header_view_is_empty (header_view)) {
1816                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1817                         GtkWidget *folder_view = 
1818                                 modest_main_window_get_child_widget (main_window,
1819                                                                      MODEST_WIDGET_TYPE_FOLDER_VIEW);
1820                         if (folder != NULL) 
1821                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1822                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1823                         return;
1824                 }
1825         }
1826         /* If no header has been selected then exit */
1827         if (!header)
1828                 return;
1829
1830         /* Update focus */
1831         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1832             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1833
1834         /* Update toolbar dimming state */
1835         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1836 }
1837
1838 void
1839 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1840                                        TnyHeader *header,
1841                                        ModestMainWindow *main_window)
1842 {
1843         TnyList *headers;
1844
1845         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1846         
1847         if (!header)
1848                 return;
1849
1850
1851 /*      headers = tny_simple_list_new (); */
1852 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1853         headers = modest_header_view_get_selected_headers (header_view);
1854
1855         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1856
1857         g_object_unref (headers);
1858 }
1859
1860 static void
1861 set_active_account_from_tny_account (TnyAccount *account,
1862                                      ModestWindow *window)
1863 {
1864         const gchar *server_acc_name = tny_account_get_id (account);
1865         
1866         /* We need the TnyAccount provided by the
1867            account store because that is the one that
1868            knows the name of the Modest account */
1869         TnyAccount *modest_server_account = modest_server_account = 
1870                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1871                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1872                                                              server_acc_name);
1873         if (!modest_server_account) {
1874                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1875                 return;
1876         }
1877
1878         /* Update active account, but only if it's not a pseudo-account */
1879         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1880             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1881                 const gchar *modest_acc_name = 
1882                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1883                 if (modest_acc_name)
1884                         modest_window_set_active_account (window, modest_acc_name);
1885         }
1886         
1887         g_object_unref (modest_server_account);
1888 }
1889
1890
1891 static void
1892 folder_refreshed_cb (ModestMailOperation *mail_op, 
1893                      TnyFolder *folder, 
1894                      gpointer user_data)
1895 {
1896         ModestMainWindow *win = NULL;
1897         GtkWidget *header_view;
1898         gboolean folder_empty = FALSE;
1899         gboolean all_marked_as_deleted = FALSE;
1900
1901         g_return_if_fail (TNY_IS_FOLDER (folder));
1902
1903         win = MODEST_MAIN_WINDOW (user_data);
1904         header_view = 
1905                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1906
1907         if (header_view) {
1908                 TnyFolder *current_folder;
1909
1910                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1911                 if (current_folder != NULL && folder != current_folder) {
1912                         g_object_unref (current_folder);
1913                         return;
1914                 }
1915                 g_object_unref (current_folder);
1916         }
1917
1918         /* Check if folder is empty and set headers view contents style */
1919         folder_empty = (tny_folder_get_all_count (folder) == 0);
1920         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1921         if (folder_empty || all_marked_as_deleted)
1922                 modest_main_window_set_contents_style (win,
1923                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1924 }
1925
1926 void 
1927 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1928                                                TnyFolderStore *folder_store, 
1929                                                gboolean selected,
1930                                                ModestMainWindow *main_window)
1931 {
1932         ModestConf *conf;
1933         GtkWidget *header_view;
1934
1935         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1936
1937         header_view = modest_main_window_get_child_widget(main_window,
1938                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1939         if (!header_view)
1940                 return;
1941         
1942         conf = modest_runtime_get_conf ();
1943
1944         if (TNY_IS_ACCOUNT (folder_store)) {
1945                 if (selected) {
1946                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1947                         
1948                         /* Show account details */
1949                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1950                 }
1951         } else {
1952                 if (TNY_IS_FOLDER (folder_store) && selected) {
1953                         
1954                         /* Update the active account */
1955                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1956                         if (account) {
1957                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1958                                 g_object_unref (account);
1959                                 account = NULL;
1960                         }
1961
1962                         /* Set the header style by default, it could
1963                            be changed later by the refresh callback to
1964                            empty */
1965                         modest_main_window_set_contents_style (main_window, 
1966                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1967
1968                         /* Set folder on header view. This function
1969                            will call tny_folder_refresh_async so we
1970                            pass a callback that will be called when
1971                            finished. We use that callback to set the
1972                            empty view if there are no messages */
1973                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1974                                                        TNY_FOLDER (folder_store),
1975                                                        folder_refreshed_cb,
1976                                                        main_window);
1977                         
1978                         /* Restore configuration. We need to do this
1979                            *after* the set_folder because the widget
1980                            memory asks the header view about its
1981                            folder  */
1982                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1983                                                       G_OBJECT(header_view),
1984                                                       MODEST_CONF_HEADER_VIEW_KEY);
1985                 } else {
1986                         /* Update the active account */
1987                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1988                         /* Save only if we're seeing headers */
1989                         if (modest_main_window_get_contents_style (main_window) ==
1990                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1991                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1992                                                            MODEST_CONF_HEADER_VIEW_KEY);
1993                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1994                 }
1995         }
1996
1997         /* Update toolbar dimming state */
1998         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1999 }
2000
2001 void 
2002 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2003                                      ModestWindow *win)
2004 {
2005         GtkWidget *dialog;
2006         gchar *txt, *item;
2007         gboolean online;
2008
2009         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2010         
2011         online = tny_device_is_online (modest_runtime_get_device());
2012
2013         if (online) {
2014                 /* already online -- the item is simply not there... */
2015                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2016                                                  GTK_DIALOG_MODAL,
2017                                                  GTK_MESSAGE_WARNING,
2018                                                  GTK_BUTTONS_NONE,
2019                                                  _("The %s you selected cannot be found"),
2020                                                  item);
2021                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2022                 gtk_dialog_run (GTK_DIALOG(dialog));
2023         } else {
2024                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2025                                                       GTK_WINDOW (win),
2026                                                       GTK_DIALOG_MODAL,
2027                                                       _("mcen_bd_dialog_cancel"),
2028                                                       GTK_RESPONSE_REJECT,
2029                                                       _("mcen_bd_dialog_ok"),
2030                                                       GTK_RESPONSE_ACCEPT,
2031                                                       NULL);
2032                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2033                                          "Do you want to get online?"), item);
2034                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2035                                     gtk_label_new (txt), FALSE, FALSE, 0);
2036                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2037                 g_free (txt);
2038
2039                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2040                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2041                         /* TODO: Comment about why is this commented out: */
2042                         /* modest_platform_connect_and_wait (); */
2043                 }
2044         }
2045         gtk_widget_destroy (dialog);
2046 }
2047
2048 void
2049 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2050                                      ModestWindow *win)
2051 {
2052         /* g_message ("%s %s", __FUNCTION__, link); */
2053 }       
2054
2055
2056 void
2057 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2058                                         ModestWindow *win)
2059 {
2060         modest_platform_activate_uri (link);
2061 }
2062
2063 void
2064 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2065                                           ModestWindow *win)
2066 {
2067         modest_platform_show_uri_popup (link);
2068 }
2069
2070 void
2071 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2072                                              ModestWindow *win)
2073 {
2074         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2075 }
2076
2077 void
2078 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2079                                           const gchar *address,
2080                                           ModestWindow *win)
2081 {
2082         /* g_message ("%s %s", __FUNCTION__, address); */
2083 }
2084
2085 void
2086 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2087 {
2088         TnyTransportAccount *transport_account;
2089         ModestMailOperation *mail_operation;
2090         MsgData *data;
2091         gchar *account_name, *from;
2092         ModestAccountMgr *account_mgr;
2093         gchar *info_text = NULL;
2094
2095         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2096         
2097         data = modest_msg_edit_window_get_msg_data (edit_window);
2098
2099         account_mgr = modest_runtime_get_account_mgr();
2100         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2101         if (!account_name) 
2102                 account_name = modest_account_mgr_get_default_account (account_mgr);
2103         if (!account_name) {
2104                 g_printerr ("modest: no account found\n");
2105                 modest_msg_edit_window_free_msg_data (edit_window, data);
2106                 return;
2107         }
2108
2109         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2110                 account_name = g_strdup (data->account_name);
2111         }
2112
2113         transport_account =
2114                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2115                                       (modest_runtime_get_account_store(),
2116                                        account_name,
2117                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2118         if (!transport_account) {
2119                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2120                 g_free (account_name);
2121                 modest_msg_edit_window_free_msg_data (edit_window, data);
2122                 return;
2123         }
2124         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2125
2126         /* Create the mail operation */         
2127         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2128         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2129
2130         modest_mail_operation_save_to_drafts (mail_operation,
2131                                               transport_account,
2132                                               data->draft_msg,
2133                                               edit_window,
2134                                               from,
2135                                               data->to, 
2136                                               data->cc, 
2137                                               data->bcc,
2138                                               data->subject, 
2139                                               data->plain_body, 
2140                                               data->html_body,
2141                                               data->attachments,
2142                                               data->priority_flags);
2143         /* Frees */
2144         g_free (from);
2145         g_free (account_name);
2146         g_object_unref (G_OBJECT (transport_account));
2147         g_object_unref (G_OBJECT (mail_operation));
2148
2149         modest_msg_edit_window_free_msg_data (edit_window, data);
2150
2151         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2152         modest_platform_information_banner (NULL, NULL, info_text);
2153         g_free (info_text);
2154 }
2155
2156 /* For instance, when clicking the Send toolbar button when editing a message: */
2157 void
2158 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2159 {
2160         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2161
2162         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2163                 return;
2164         
2165         /* Offer the connection dialog, if necessary: */        
2166         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2167                 return;
2168         
2169         /* FIXME: Code added just for testing. The final version will
2170            use the send queue provided by tinymail and some
2171            classifier */
2172         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2173         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2174         if (!account_name) 
2175                 account_name = modest_account_mgr_get_default_account (account_mgr);
2176                 
2177         if (!account_name) {
2178                 /* Run account setup wizard */
2179                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2180                 if (!created)
2181                         return;
2182         }
2183         
2184         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2185
2186         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2187                 account_name = g_strdup (data->account_name);
2188         }
2189         
2190         /* Get the currently-active transport account for this modest account: */
2191         TnyTransportAccount *transport_account =
2192                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2193                                       (modest_runtime_get_account_store(),
2194                                        account_name));
2195         if (!transport_account) {
2196                 /* Run account setup wizard */
2197                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2198                 if (!created)
2199                         return;
2200         }
2201         
2202         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2203
2204         /* Create the mail operation */
2205         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2206         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2207
2208         modest_mail_operation_send_new_mail (mail_operation,
2209                                              transport_account,
2210                                              data->draft_msg,
2211                                              from,
2212                                              data->to, 
2213                                              data->cc, 
2214                                              data->bcc,
2215                                              data->subject, 
2216                                              data->plain_body, 
2217                                              data->html_body,
2218                                              data->attachments,
2219                                              data->priority_flags);
2220                                              
2221         /* Free data: */
2222         g_free (from);
2223         g_free (account_name);
2224         g_object_unref (G_OBJECT (transport_account));
2225         g_object_unref (G_OBJECT (mail_operation));
2226
2227         modest_msg_edit_window_free_msg_data (edit_window, data);
2228         modest_msg_edit_window_set_sent (edit_window, TRUE);
2229
2230         /* Save settings and close the window: */
2231         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2232 }
2233
2234 void 
2235 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2236                                   ModestMsgEditWindow *window)
2237 {
2238         ModestMsgEditFormatState *format_state = NULL;
2239
2240         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2241         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2242
2243         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2244                 return;
2245
2246         format_state = modest_msg_edit_window_get_format_state (window);
2247         g_return_if_fail (format_state != NULL);
2248
2249         format_state->bold = gtk_toggle_action_get_active (action);
2250         modest_msg_edit_window_set_format_state (window, format_state);
2251         g_free (format_state);
2252         
2253 }
2254
2255 void 
2256 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2257                                      ModestMsgEditWindow *window)
2258 {
2259         ModestMsgEditFormatState *format_state = NULL;
2260
2261         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2262         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2263
2264         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2265                 return;
2266
2267         format_state = modest_msg_edit_window_get_format_state (window);
2268         g_return_if_fail (format_state != NULL);
2269
2270         format_state->italics = gtk_toggle_action_get_active (action);
2271         modest_msg_edit_window_set_format_state (window, format_state);
2272         g_free (format_state);
2273         
2274 }
2275
2276 void 
2277 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2278                                      ModestMsgEditWindow *window)
2279 {
2280         ModestMsgEditFormatState *format_state = NULL;
2281
2282         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2283         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2284
2285         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2286                 return;
2287
2288         format_state = modest_msg_edit_window_get_format_state (window);
2289         g_return_if_fail (format_state != NULL);
2290
2291         format_state->bullet = gtk_toggle_action_get_active (action);
2292         modest_msg_edit_window_set_format_state (window, format_state);
2293         g_free (format_state);
2294         
2295 }
2296
2297 void 
2298 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2299                                      GtkRadioAction *selected,
2300                                      ModestMsgEditWindow *window)
2301 {
2302         ModestMsgEditFormatState *format_state = NULL;
2303         GtkJustification value;
2304
2305         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2306
2307         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2308                 return;
2309
2310         value = gtk_radio_action_get_current_value (selected);
2311
2312         format_state = modest_msg_edit_window_get_format_state (window);
2313         g_return_if_fail (format_state != NULL);
2314
2315         format_state->justification = value;
2316         modest_msg_edit_window_set_format_state (window, format_state);
2317         g_free (format_state);
2318 }
2319
2320 void 
2321 modest_ui_actions_on_select_editor_color (GtkAction *action,
2322                                           ModestMsgEditWindow *window)
2323 {
2324         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2325         g_return_if_fail (GTK_IS_ACTION (action));
2326
2327         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2328                 return;
2329
2330         modest_msg_edit_window_select_color (window);
2331 }
2332
2333 void 
2334 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2335                                                      ModestMsgEditWindow *window)
2336 {
2337         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2338         g_return_if_fail (GTK_IS_ACTION (action));
2339
2340         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2341                 return;
2342
2343         modest_msg_edit_window_select_background_color (window);
2344 }
2345
2346 void 
2347 modest_ui_actions_on_insert_image (GtkAction *action,
2348                                    ModestMsgEditWindow *window)
2349 {
2350         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2351         g_return_if_fail (GTK_IS_ACTION (action));
2352
2353         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2354                 return;
2355
2356         modest_msg_edit_window_insert_image (window);
2357 }
2358
2359 void 
2360 modest_ui_actions_on_attach_file (GtkAction *action,
2361                                   ModestMsgEditWindow *window)
2362 {
2363         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2364         g_return_if_fail (GTK_IS_ACTION (action));
2365
2366         modest_msg_edit_window_offer_attach_file (window);
2367 }
2368
2369 void 
2370 modest_ui_actions_on_remove_attachments (GtkAction *action,
2371                                          ModestMsgEditWindow *window)
2372 {
2373         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2374         g_return_if_fail (GTK_IS_ACTION (action));
2375
2376         modest_msg_edit_window_remove_attachments (window, NULL);
2377 }
2378
2379 static void
2380 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2381                                             gpointer user_data)
2382 {
2383         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2384         const GError *error = modest_mail_operation_get_error (mail_op);
2385
2386         if(error)
2387         {
2388                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2389                                                     modest_mail_operation_get_error (mail_op)->message);
2390         }
2391 }
2392
2393 static void
2394 modest_ui_actions_create_folder(GtkWidget *parent_window,
2395                                 GtkWidget *folder_view)
2396 {
2397         TnyFolderStore *parent_folder;
2398
2399         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2400         
2401         if (parent_folder) {
2402                 gboolean finished = FALSE;
2403                 gint result;
2404                 gchar *folder_name = NULL, *suggested_name = NULL;
2405                 const gchar *proto_str = NULL;
2406                 TnyAccount *account;
2407
2408                 if (TNY_IS_ACCOUNT (parent_folder))
2409                         account = g_object_ref (parent_folder);
2410                 else
2411                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2412                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2413
2414                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2415                     MODEST_PROTOCOL_STORE_POP) {
2416                         finished = TRUE;
2417                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2418                 }
2419                 g_object_unref (account);
2420
2421                 /* Run the new folder dialog */
2422                 while (!finished) {
2423                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2424                                                                         parent_folder,
2425                                                                         suggested_name,
2426                                                                         &folder_name);
2427
2428                         g_free (suggested_name);
2429                         suggested_name = NULL;
2430
2431                         if (result == GTK_RESPONSE_REJECT) {
2432                                 finished = TRUE;
2433                         } else {
2434                                 ModestMailOperation *mail_op;
2435                                 TnyFolder *new_folder = NULL;
2436
2437                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2438                                                                                           G_OBJECT(parent_window),
2439                                                                                           modest_ui_actions_new_folder_error_handler,
2440                                                                                           parent_window);
2441
2442                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2443                                                                  mail_op);
2444                                 new_folder = modest_mail_operation_create_folder (mail_op,
2445                                                                                   parent_folder,
2446                                                                                   (const gchar *) folder_name);
2447                                 if (new_folder) {
2448                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2449                                                                           new_folder, TRUE);
2450
2451                                         g_object_unref (new_folder);
2452                                         finished = TRUE;
2453                                 }
2454                                 g_object_unref (mail_op);
2455                         }
2456
2457                         suggested_name = folder_name;
2458                         folder_name = NULL;
2459                 }
2460
2461                 g_object_unref (parent_folder);
2462         }
2463 }
2464
2465 void 
2466 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2467 {
2468         GtkWidget *folder_view;
2469         
2470         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2471
2472         folder_view = modest_main_window_get_child_widget (main_window,
2473                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2474         if (!folder_view)
2475                 return;
2476
2477         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2478 }
2479
2480 static void
2481 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2482                                                gpointer user_data)
2483 {
2484         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2485         const GError *error = NULL;
2486         const gchar *message = NULL;
2487         
2488         /* Get error message */
2489         error = modest_mail_operation_get_error (mail_op);
2490         if (!error)
2491                 g_return_if_reached ();
2492
2493         switch (error->code) {
2494         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2495                 message = _CS("ckdg_ib_folder_already_exists");
2496                 break;
2497         default:
2498                 g_return_if_reached ();
2499         }
2500
2501         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2502 }
2503
2504 void 
2505 modest_ui_actions_on_rename_folder (GtkAction *action,
2506                                      ModestMainWindow *main_window)
2507 {
2508         TnyFolderStore *folder;
2509         GtkWidget *folder_view;
2510         GtkWidget *header_view; 
2511
2512         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2513
2514         folder_view = modest_main_window_get_child_widget (main_window,
2515                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2516         if (!folder_view)
2517                 return;
2518
2519         header_view = modest_main_window_get_child_widget (main_window,
2520                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2521         
2522         if (!header_view)
2523                 return;
2524
2525         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2526
2527         if (!folder)
2528                 return;
2529
2530         if (TNY_IS_FOLDER (folder)) {
2531                 gchar *folder_name;
2532                 gint response;
2533                 const gchar *current_name;
2534                 TnyFolderStore *parent;
2535                 gboolean do_rename = TRUE;
2536
2537                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2538                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2539                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2540                                                                      parent, current_name, 
2541                                                                      &folder_name);
2542                 g_object_unref (parent);
2543
2544                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2545                         do_rename = FALSE;
2546                 } else if (modest_platform_is_network_folderstore(folder) &&
2547                            !tny_device_is_online (modest_runtime_get_device())) {
2548                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2549                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2550                         g_object_unref(account);
2551                 }
2552
2553                 if (do_rename) {
2554                         ModestMailOperation *mail_op;
2555                         GtkTreeSelection *sel = NULL;
2556
2557                         mail_op = 
2558                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2559                                                                                G_OBJECT(main_window),
2560                                                                                modest_ui_actions_rename_folder_error_handler,
2561                                                                                main_window);
2562
2563                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2564                                                          mail_op);
2565
2566                         /* Clear the headers view */
2567                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2568                         gtk_tree_selection_unselect_all (sel);
2569
2570                         /* Select *after* the changes */
2571                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2572                                                           TNY_FOLDER(folder), TRUE);
2573
2574                         /* Actually rename the folder */
2575                         modest_mail_operation_rename_folder (mail_op,
2576                                                              TNY_FOLDER (folder),
2577                                                              (const gchar *) folder_name);
2578
2579                         g_object_unref (mail_op);
2580                         g_free (folder_name);
2581                 }
2582         }
2583         g_object_unref (folder);
2584 }
2585
2586 static void
2587 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2588                                                gpointer user_data)
2589 {
2590         GObject *win = modest_mail_operation_get_source (mail_op);
2591
2592         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2593                                                 _("mail_in_ui_folder_delete_error"));
2594         g_object_unref (win);
2595 }
2596
2597 static void
2598 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2599 {
2600         TnyFolderStore *folder;
2601         GtkWidget *folder_view;
2602         gint response;
2603         gchar *message;
2604         gboolean do_delete = TRUE;
2605
2606         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2607
2608         folder_view = modest_main_window_get_child_widget (main_window,
2609                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2610         if (!folder_view)
2611                 return;
2612
2613         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2614
2615         /* Show an error if it's an account */
2616         if (!TNY_IS_FOLDER (folder)) {
2617                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2618                                                         _("mail_in_ui_folder_delete_error"));
2619                 g_object_unref (G_OBJECT (folder));
2620                 return ;
2621         }
2622
2623         /* Ask the user */      
2624         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2625                                     tny_folder_get_name (TNY_FOLDER (folder)));
2626         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2627                                                             (const gchar *) message);
2628         g_free (message);
2629
2630         if (response != GTK_RESPONSE_OK) {
2631                 do_delete = FALSE;
2632         } else if (modest_platform_is_network_folderstore(folder) &&
2633                    !tny_device_is_online (modest_runtime_get_device())) {
2634                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2635                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2636                 g_object_unref(account);
2637         }
2638
2639         if (do_delete) {
2640                 ModestMailOperation *mail_op;
2641                 GtkTreeSelection *sel;
2642
2643                 /* Unselect the folder before deleting it to free the headers */
2644                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2645                 gtk_tree_selection_unselect_all (sel);
2646
2647                 /* Create the mail operation */
2648                 mail_op =
2649                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2650                                                                        G_OBJECT(main_window),
2651                                                                        modest_ui_actions_delete_folder_error_handler,
2652                                                                        NULL);
2653
2654                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2655                                                  mail_op);
2656                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2657                 g_object_unref (G_OBJECT (mail_op));
2658         }
2659
2660         g_object_unref (G_OBJECT (folder));
2661 }
2662
2663 void 
2664 modest_ui_actions_on_delete_folder (GtkAction *action,
2665                                      ModestMainWindow *main_window)
2666 {
2667         GtkWidget *folder_view;
2668         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2669
2670         delete_folder (main_window, FALSE);
2671         folder_view = modest_main_window_get_child_widget (main_window,
2672                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2673         if (!folder_view)
2674                 return;
2675         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2676 }
2677
2678 void 
2679 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2680 {
2681         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2682         
2683         delete_folder (main_window, TRUE);
2684 }
2685
2686
2687 static void
2688 show_error (GtkWidget *parent_widget, const gchar* text)
2689 {
2690         hildon_banner_show_information(parent_widget, NULL, text);
2691         
2692 #if 0
2693         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2694         /*
2695           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2696           (GtkDialogFlags)0,
2697           GTK_MESSAGE_ERROR,
2698           GTK_BUTTONS_OK,
2699           text ));
2700         */
2701                  
2702         gtk_dialog_run (dialog);
2703         gtk_widget_destroy (GTK_WIDGET (dialog));
2704 #endif
2705 }
2706
2707 void
2708 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2709                                          const gchar* server_account_name,
2710                                          gchar **username,
2711                                          gchar **password, 
2712                                          gboolean *cancel, 
2713                                          gboolean *remember,
2714                                          ModestMainWindow *main_window)
2715 {
2716         g_return_if_fail(server_account_name);
2717         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2718         
2719         /* Initalize output parameters: */
2720         if (cancel)
2721                 *cancel = FALSE;
2722                 
2723         if (remember)
2724                 *remember = TRUE;
2725                 
2726 #ifdef MODEST_PLATFORM_MAEMO
2727         /* Maemo uses a different (awkward) button order,
2728          * It should probably just use gtk_alternative_dialog_button_order ().
2729          */
2730         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2731                                               NULL,
2732                                               GTK_DIALOG_MODAL,
2733                                               _("mcen_bd_dialog_ok"),
2734                                               GTK_RESPONSE_ACCEPT,
2735                                               _("mcen_bd_dialog_cancel"),
2736                                               GTK_RESPONSE_REJECT,
2737                                               NULL);
2738 #else
2739         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2740                                               NULL,
2741                                               GTK_DIALOG_MODAL,
2742                                               GTK_STOCK_CANCEL,
2743                                               GTK_RESPONSE_REJECT,
2744                                               GTK_STOCK_OK,
2745                                               GTK_RESPONSE_ACCEPT,
2746                                               NULL);
2747 #endif /* MODEST_PLATFORM_MAEMO */
2748
2749         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2750         
2751         gchar *server_name = modest_server_account_get_hostname (
2752                 modest_runtime_get_account_mgr(), server_account_name);
2753         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2754                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2755                 *cancel = TRUE;
2756                 return;
2757         }
2758         
2759         /* This causes a warning because the logical ID has no %s in it, 
2760          * though the translation does, but there is not much we can do about that: */
2761         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2762         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2763                             FALSE, FALSE, 0);
2764         g_free (txt);
2765         g_free (server_name);
2766         server_name = NULL;
2767
2768         /* username: */
2769         gchar *initial_username = modest_server_account_get_username (
2770                 modest_runtime_get_account_mgr(), server_account_name);
2771         
2772         GtkWidget *entry_username = gtk_entry_new ();
2773         if (initial_username)
2774                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2775         /* Dim this if a connection has ever succeeded with this username,
2776          * as per the UI spec: */
2777         const gboolean username_known = 
2778                 modest_server_account_get_username_has_succeeded(
2779                         modest_runtime_get_account_mgr(), server_account_name);
2780         gtk_widget_set_sensitive (entry_username, !username_known);
2781         
2782 #ifdef MODEST_PLATFORM_MAEMO
2783         /* Auto-capitalization is the default, so let's turn it off: */
2784         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2785         
2786         /* Create a size group to be used by all captions.
2787          * Note that HildonCaption does not create a default size group if we do not specify one.
2788          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2789         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2790         
2791         GtkWidget *caption = hildon_caption_new (sizegroup, 
2792                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2793         gtk_widget_show (entry_username);
2794         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2795                 FALSE, FALSE, MODEST_MARGIN_HALF);
2796         gtk_widget_show (caption);
2797 #else 
2798         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2799                             TRUE, FALSE, 0);
2800 #endif /* MODEST_PLATFORM_MAEMO */      
2801                             
2802         /* password: */
2803         GtkWidget *entry_password = gtk_entry_new ();
2804         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2805         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2806         
2807 #ifdef MODEST_PLATFORM_MAEMO
2808         /* Auto-capitalization is the default, so let's turn it off: */
2809         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2810                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2811         
2812         caption = hildon_caption_new (sizegroup, 
2813                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2814         gtk_widget_show (entry_password);
2815         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2816                 FALSE, FALSE, MODEST_MARGIN_HALF);
2817         gtk_widget_show (caption);
2818         g_object_unref (sizegroup);
2819 #else 
2820         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2821                             TRUE, FALSE, 0);
2822 #endif /* MODEST_PLATFORM_MAEMO */      
2823                                 
2824 /* This is not in the Maemo UI spec:
2825         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2826         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2827                             TRUE, FALSE, 0);
2828 */
2829
2830         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2831         
2832         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2833                 if (username) {
2834                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2835                         
2836                         modest_server_account_set_username (
2837                                  modest_runtime_get_account_mgr(), server_account_name, 
2838                                  *username);
2839                                  
2840                         const gboolean username_was_changed = 
2841                                 (strcmp (*username, initial_username) != 0);
2842                         if (username_was_changed) {
2843                                 g_warning ("%s: tinymail does not yet support changing the "
2844                                         "username in the get_password() callback.\n", __FUNCTION__);
2845                         }
2846                 }
2847                         
2848                 if (password) {
2849                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2850                         
2851                         /* We do not save the password in the configuration, 
2852                          * because this function is only called for passwords that should 
2853                          * not be remembered:
2854                         modest_server_account_set_password (
2855                                  modest_runtime_get_account_mgr(), server_account_name, 
2856                                  *password);
2857                         */
2858                 }
2859                 
2860                 if (cancel)
2861                         *cancel   = FALSE;
2862                         
2863         } else {
2864                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2865                 
2866                 if (username)
2867                         *username = NULL;
2868                         
2869                 if (password)
2870                         *password = NULL;
2871                         
2872                 if (cancel)
2873                         *cancel   = TRUE;
2874         }
2875
2876 /* This is not in the Maemo UI spec:
2877         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2878                 *remember = TRUE;
2879         else
2880                 *remember = FALSE;
2881 */
2882
2883         gtk_widget_destroy (dialog);
2884         
2885         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2886 }
2887
2888 void
2889 modest_ui_actions_on_cut (GtkAction *action,
2890                           ModestWindow *window)
2891 {
2892         GtkWidget *focused_widget;
2893         GtkClipboard *clipboard;
2894
2895         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2896         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2897         if (GTK_IS_EDITABLE (focused_widget)) {
2898                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2899                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2900                 gtk_clipboard_store (clipboard);
2901         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2902                 GtkTextBuffer *buffer;
2903
2904                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2905                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2906                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2907                 gtk_clipboard_store (clipboard);
2908         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2909                 TnyList *header_list = modest_header_view_get_selected_headers (
2910                                 MODEST_HEADER_VIEW (focused_widget));
2911                 gboolean continue_download = FALSE;
2912                 gint num_of_unc_msgs;
2913
2914                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2915
2916                 if (num_of_unc_msgs)
2917                         continue_download = connect_to_get_msg(
2918                                                                 GTK_WINDOW (window),
2919                                                                 num_of_unc_msgs);
2920
2921                 if (num_of_unc_msgs == 0 || continue_download) {
2922 /*                      modest_platform_information_banner (
2923                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2924                         modest_header_view_cut_selection (
2925                                         MODEST_HEADER_VIEW (focused_widget));
2926                 }
2927
2928                 g_object_unref (header_list);
2929         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2930                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2931         }
2932 }
2933
2934 void
2935 modest_ui_actions_on_copy (GtkAction *action,
2936                            ModestWindow *window)
2937 {
2938         GtkClipboard *clipboard;
2939         GtkWidget *focused_widget;
2940         gboolean copied = TRUE;
2941
2942         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2943         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2944
2945         if (GTK_IS_LABEL (focused_widget)) {
2946                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2947                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2948                 gtk_clipboard_store (clipboard);
2949         } else if (GTK_IS_EDITABLE (focused_widget)) {
2950                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2951                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2952                 gtk_clipboard_store (clipboard);
2953         } else if (GTK_IS_HTML (focused_widget)) {
2954                 gtk_html_copy (GTK_HTML (focused_widget));
2955                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2956                 gtk_clipboard_store (clipboard);
2957         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2958                 GtkTextBuffer *buffer;
2959                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2960                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2961                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2962                 gtk_clipboard_store (clipboard);
2963         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2964                 TnyList *header_list = modest_header_view_get_selected_headers (
2965                                 MODEST_HEADER_VIEW (focused_widget));
2966                 gboolean continue_download = FALSE;
2967                 gint num_of_unc_msgs;
2968
2969                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2970
2971                 if (num_of_unc_msgs)
2972                         continue_download = connect_to_get_msg(
2973                                                                 GTK_WINDOW (window),
2974                                                                 num_of_unc_msgs);
2975
2976                 if (num_of_unc_msgs == 0 || continue_download) {
2977                         modest_platform_information_banner (
2978                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2979                         modest_header_view_copy_selection (
2980                                         MODEST_HEADER_VIEW (focused_widget));
2981                 } else
2982                         copied = FALSE;
2983
2984                 g_object_unref (header_list);
2985
2986         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2987                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2988         }
2989
2990         /* Show information banner if there was a copy to clipboard */
2991         if(copied)
2992                 modest_platform_information_banner (
2993                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2994 }
2995
2996 void
2997 modest_ui_actions_on_undo (GtkAction *action,
2998                            ModestWindow *window)
2999 {
3000         ModestEmailClipboard *clipboard = NULL;
3001
3002         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3003                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3004         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3005                 /* Clear clipboard source */
3006                 clipboard = modest_runtime_get_email_clipboard ();
3007                 modest_email_clipboard_clear (clipboard);               
3008         }
3009         else {
3010                 g_return_if_reached ();
3011         }
3012 }
3013
3014 void
3015 modest_ui_actions_on_redo (GtkAction *action,
3016                            ModestWindow *window)
3017 {
3018         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3019                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3020         }
3021         else {
3022                 g_return_if_reached ();
3023         }
3024 }
3025
3026
3027 static void
3028 paste_msgs_cb (const GObject *object, gpointer user_data)
3029 {
3030         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
3031         g_return_if_fail (GTK_IS_WIDGET (user_data));
3032         
3033         /* destroy information note */
3034         gtk_widget_destroy (GTK_WIDGET(user_data));
3035 }
3036
3037
3038 static void
3039 paste_as_attachment_free (gpointer data)
3040 {
3041         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3042
3043         gtk_widget_destroy (helper->banner);
3044         g_object_unref (helper->banner);
3045         g_free (helper);
3046 }
3047
3048 static void
3049 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3050                             TnyHeader *header,
3051                             TnyMsg *msg,
3052                             gpointer userdata)
3053 {
3054         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3055         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3056
3057         if (msg == NULL)
3058                 return;
3059
3060         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3061         
3062 }
3063
3064 void
3065 modest_ui_actions_on_paste (GtkAction *action,
3066                             ModestWindow *window)
3067 {
3068         GtkWidget *focused_widget = NULL;
3069         GtkWidget *inf_note = NULL;
3070         ModestMailOperation *mail_op = NULL;
3071
3072         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3073         if (GTK_IS_EDITABLE (focused_widget)) {
3074                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3075         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3076                 ModestEmailClipboard *e_clipboard = NULL;
3077                 e_clipboard = modest_runtime_get_email_clipboard ();
3078                 if (modest_email_clipboard_cleared (e_clipboard)) {
3079                         GtkTextBuffer *buffer;
3080                         GtkClipboard *clipboard;
3081
3082                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3083                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3084                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3085                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3086                         ModestMailOperation *mail_op;
3087                         TnyFolder *src_folder;
3088                         TnyList *data;
3089                         gboolean delete;
3090                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3091                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3092                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3093                                                                            _CS("ckct_nw_pasting"));
3094                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3095                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3096                                                              G_OBJECT (window));
3097                         if (helper->banner != NULL) {
3098                                 g_object_ref (G_OBJECT (helper->banner));
3099                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3100                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3101                         }
3102
3103                         if (data != NULL) {
3104                                 modest_mail_operation_get_msgs_full (mail_op, 
3105                                                                      data,
3106                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3107                                                                      helper,
3108                                                                      paste_as_attachment_free);
3109                         }
3110                 }
3111         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3112                 ModestEmailClipboard *clipboard = NULL;
3113                 TnyFolder *src_folder = NULL;
3114                 TnyFolderStore *folder_store = NULL;
3115                 TnyList *data = NULL;           
3116                 gboolean delete = FALSE;
3117                 
3118                 /* Check clipboard source */
3119                 clipboard = modest_runtime_get_email_clipboard ();
3120                 if (modest_email_clipboard_cleared (clipboard)) 
3121                         return;
3122                 
3123                 /* Get elements to paste */
3124                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3125
3126                 /* Create a new mail operation */
3127                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3128                 
3129                 /* Get destination folder */
3130                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3131
3132                 /* transfer messages  */
3133                 if (data != NULL) {
3134                         gint response = 0;
3135
3136                         /* Ask for user confirmation */
3137                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3138                                                               TNY_FOLDER (folder_store), 
3139                                                               delete,
3140                                                               data);
3141                         
3142                         if (response == GTK_RESPONSE_OK) {
3143                                 /* Launch notification */
3144                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3145                                                                              _CS("ckct_nw_pasting"));
3146                                 if (inf_note != NULL)  {
3147                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3148                                         gtk_widget_show (GTK_WIDGET(inf_note));
3149                                 }
3150
3151                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3152                                 modest_mail_operation_xfer_msgs (mail_op, 
3153                                                                  data,
3154                                                                  TNY_FOLDER (folder_store),
3155                                                                  delete,
3156                                                                  paste_msgs_cb,
3157                                                                  inf_note);                             
3158                         } else {
3159                                 g_object_unref (mail_op);
3160                         }
3161                         
3162                 } else if (src_folder != NULL) {                        
3163                         /* Launch notification */
3164                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3165                                                                      _CS("ckct_nw_pasting"));
3166                         if (inf_note != NULL)  {
3167                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3168                                 gtk_widget_show (GTK_WIDGET(inf_note));
3169                         }
3170                         
3171                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3172                         modest_mail_operation_xfer_folder (mail_op, 
3173                                                            src_folder,
3174                                                            folder_store,
3175                                                            delete,
3176                                                            paste_msgs_cb,
3177                                                            inf_note);
3178                 }
3179
3180                 /* Free */
3181                 if (data != NULL) 
3182                         g_object_unref (data);
3183                 if (src_folder != NULL) 
3184                         g_object_unref (src_folder);
3185                 if (folder_store != NULL) 
3186                         g_object_unref (folder_store);
3187         }
3188 }
3189
3190
3191 void
3192 modest_ui_actions_on_select_all (GtkAction *action,
3193                                  ModestWindow *window)
3194 {
3195         GtkWidget *focused_widget;
3196
3197         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3198         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3199                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3200         } else if (GTK_IS_LABEL (focused_widget)) {
3201                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3202         } else if (GTK_IS_EDITABLE (focused_widget)) {
3203                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3204         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3205                 GtkTextBuffer *buffer;
3206                 GtkTextIter start, end;
3207
3208                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3209                 gtk_text_buffer_get_start_iter (buffer, &start);
3210                 gtk_text_buffer_get_end_iter (buffer, &end);
3211                 gtk_text_buffer_select_range (buffer, &start, &end);
3212         } else if (GTK_IS_HTML (focused_widget)) {
3213                 gtk_html_select_all (GTK_HTML (focused_widget));
3214         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3215                 GtkWidget *header_view = focused_widget;
3216                 GtkTreeSelection *selection = NULL;
3217                 
3218                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3219                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3220                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3221                 }
3222                                 
3223                 /* Disable window dimming management */
3224                 modest_window_disable_dimming (MODEST_WINDOW(window));
3225                 
3226                 /* Select all messages */
3227                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3228                 gtk_tree_selection_select_all (selection);
3229
3230                 /* Set focuse on header view */
3231                 gtk_widget_grab_focus (header_view);
3232
3233
3234                 /* Enable window dimming management */
3235                 modest_window_enable_dimming (MODEST_WINDOW(window));
3236                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3237         }
3238
3239 }
3240
3241 void
3242 modest_ui_actions_on_mark_as_read (GtkAction *action,
3243                                    ModestWindow *window)
3244 {       
3245         g_return_if_fail (MODEST_IS_WINDOW(window));
3246                 
3247         /* Mark each header as read */
3248         do_headers_action (window, headers_action_mark_as_read, NULL);
3249 }
3250
3251 void
3252 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3253                                      ModestWindow *window)
3254 {       
3255         g_return_if_fail (MODEST_IS_WINDOW(window));
3256                 
3257         /* Mark each header as read */
3258         do_headers_action (window, headers_action_mark_as_unread, NULL);
3259 }
3260
3261 void
3262 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3263                                   GtkRadioAction *selected,
3264                                   ModestWindow *window)
3265 {
3266         gint value;
3267
3268         value = gtk_radio_action_get_current_value (selected);
3269         if (MODEST_IS_WINDOW (window)) {
3270                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3271         }
3272 }
3273
3274 void     
3275 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3276                                                GtkRadioAction *selected,
3277                                                ModestWindow *window)
3278 {
3279         TnyHeaderFlags flags;
3280         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3281
3282         flags = gtk_radio_action_get_current_value (selected);
3283         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3284 }
3285
3286 void     
3287 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3288                                                   GtkRadioAction *selected,
3289                                                   ModestWindow *window)
3290 {
3291         gint file_format;
3292
3293         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3294
3295         file_format = gtk_radio_action_get_current_value (selected);
3296         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3297 }
3298
3299
3300 void     
3301 modest_ui_actions_on_zoom_plus (GtkAction *action,
3302                                 ModestWindow *window)
3303 {
3304         g_return_if_fail (MODEST_IS_WINDOW (window));
3305
3306         modest_window_zoom_plus (MODEST_WINDOW (window));
3307 }
3308
3309 void     
3310 modest_ui_actions_on_zoom_minus (GtkAction *action,
3311                                  ModestWindow *window)
3312 {
3313         g_return_if_fail (MODEST_IS_WINDOW (window));
3314
3315         modest_window_zoom_minus (MODEST_WINDOW (window));
3316 }
3317
3318 void     
3319 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3320                                            ModestWindow *window)
3321 {
3322         ModestWindowMgr *mgr;
3323         gboolean fullscreen, active;
3324         g_return_if_fail (MODEST_IS_WINDOW (window));
3325
3326         mgr = modest_runtime_get_window_mgr ();
3327
3328         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3329         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3330
3331         if (active != fullscreen) {
3332                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3333                 gtk_window_present (GTK_WINDOW (window));
3334         }
3335 }
3336
3337 void
3338 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3339                                         ModestWindow *window)
3340 {
3341         ModestWindowMgr *mgr;
3342         gboolean fullscreen;
3343
3344         g_return_if_fail (MODEST_IS_WINDOW (window));
3345
3346         mgr = modest_runtime_get_window_mgr ();
3347         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3348         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3349
3350         gtk_window_present (GTK_WINDOW (window));
3351 }
3352
3353 /* 
3354  * Used by modest_ui_actions_on_details to call do_headers_action 
3355  */
3356 static void
3357 headers_action_show_details (TnyHeader *header, 
3358                              ModestWindow *window,
3359                              gpointer user_data)
3360
3361 {
3362         GtkWidget *dialog;
3363         
3364         /* Create dialog */
3365         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3366
3367         /* Run dialog */
3368         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3369         gtk_widget_show_all (dialog);
3370         gtk_dialog_run (GTK_DIALOG (dialog));
3371
3372         gtk_widget_destroy (dialog);
3373 }
3374
3375 /*
3376  * Show the folder details in a ModestDetailsDialog widget
3377  */
3378 static void
3379 show_folder_details (TnyFolder *folder, 
3380                      GtkWindow *window)
3381 {
3382         GtkWidget *dialog;
3383         
3384         /* Create dialog */
3385         dialog = modest_details_dialog_new_with_folder (window, folder);
3386
3387         /* Run dialog */
3388         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3389         gtk_widget_show_all (dialog);
3390         gtk_dialog_run (GTK_DIALOG (dialog));
3391
3392         gtk_widget_destroy (dialog);
3393 }
3394
3395 /*
3396  * Show the header details in a ModestDetailsDialog widget
3397  */
3398 void     
3399 modest_ui_actions_on_details (GtkAction *action, 
3400                               ModestWindow *win)
3401 {
3402         TnyList * headers_list;
3403         TnyIterator *iter;
3404         TnyHeader *header;              
3405
3406         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3407                 TnyMsg *msg;
3408
3409                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3410                 if (!msg)
3411                         return;
3412                 g_object_unref (msg);           
3413
3414                 headers_list = get_selected_headers (win);
3415                 if (!headers_list)
3416                         return;
3417
3418                 iter = tny_list_create_iterator (headers_list);
3419
3420                 header = TNY_HEADER (tny_iterator_get_current (iter));
3421                 if (header) {
3422                         headers_action_show_details (header, win, NULL);
3423                         g_object_unref (header);
3424                 }
3425
3426                 g_object_unref (iter);
3427                 g_object_unref (headers_list);
3428
3429         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3430                 GtkWidget *folder_view, *header_view;
3431
3432                 /* Check which widget has the focus */
3433                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3434                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3435                 if (gtk_widget_is_focus (folder_view)) {
3436                         TnyFolderStore *folder_store
3437                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3438                         if (!folder_store) {
3439                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3440                                 return; 
3441                         }
3442                         /* Show only when it's a folder */
3443                         /* This function should not be called for account items, 
3444                          * because we dim the menu item for them. */
3445                         if (TNY_IS_FOLDER (folder_store)) {
3446                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3447                         }
3448
3449                         g_object_unref (folder_store);
3450
3451                 } else {
3452                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3453                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3454                         /* Show details of each header */
3455                         do_headers_action (win, headers_action_show_details, header_view);
3456                 }
3457         }
3458 }
3459
3460 void     
3461 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3462                                      ModestMsgEditWindow *window)
3463 {
3464         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3465
3466         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3467 }
3468
3469 void     
3470 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3471                                       ModestMsgEditWindow *window)
3472 {
3473         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3474
3475         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3476 }
3477
3478 void
3479 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3480                                        ModestMainWindow *main_window)
3481 {
3482         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3483
3484         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3485                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3486         else
3487                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3488 }
3489
3490 void 
3491 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3492                                      ModestWindow *window)
3493 {
3494         gboolean active, fullscreen = FALSE;
3495         ModestWindowMgr *mgr;
3496
3497         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3498
3499         /* Check if we want to toggle the toolbar vuew in fullscreen
3500            or normal mode */
3501         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3502                      "ViewShowToolbarFullScreen")) {
3503                 fullscreen = TRUE;
3504         }
3505
3506         /* Toggle toolbar */
3507         mgr = modest_runtime_get_window_mgr ();
3508         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3509 }
3510
3511 void     
3512 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3513                                            ModestMsgEditWindow *window)
3514 {
3515         modest_msg_edit_window_select_font (window);
3516 }
3517
3518 void
3519 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3520                                                   const gchar *display_name,
3521                                                   GtkWindow *window)
3522 {
3523         /* Do not change the application name if the widget has not
3524            the focus. This callback could be called even if the folder
3525            view has not the focus, because the handled signal could be
3526            emitted when the folder view is redrawn */
3527         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3528                 if (display_name)
3529                         gtk_window_set_title (window, display_name);
3530                 else
3531                         gtk_window_set_title (window, " ");
3532         }
3533 }
3534
3535 void
3536 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3537 {
3538         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3539         modest_msg_edit_window_select_contacts (window);
3540 }
3541
3542 void
3543 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3544 {
3545         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3546         modest_msg_edit_window_check_names (window, FALSE);
3547 }
3548
3549 static void
3550 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3551 {
3552         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3553                                          GTK_WIDGET (user_data));
3554 }
3555
3556 /*
3557  * This function is used to track changes in the selection of the
3558  * folder view that is inside the "move to" dialog to enable/disable
3559  * the OK button because we do not want the user to select a disallowed
3560  * destination for a folder.
3561  * The user also not desired to be able to use NEW button on items where
3562  * folder creation is not possibel.
3563  */
3564 static void
3565 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3566                                             TnyFolderStore *folder_store,
3567                                             gboolean selected,
3568                                             gpointer user_data)
3569 {
3570         GtkWidget *dialog = NULL;
3571         GtkWidget *ok_button = NULL, *new_button = NULL;
3572         GList *children = NULL;
3573         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3574         gboolean moving_folder = FALSE;
3575         gboolean is_local_account = TRUE;
3576         GtkWidget *folder_view = NULL;
3577         ModestTnyFolderRules rules;
3578
3579         if (!selected)
3580                 return;
3581
3582         /* Get the OK button */
3583         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3584         if (!dialog)
3585                 return;
3586
3587         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3588         ok_button = GTK_WIDGET (children->next->next->data);
3589         new_button = GTK_WIDGET (children->next->data);
3590         g_list_free (children);
3591
3592         /* check if folder_store is an remote account */
3593         if (TNY_IS_ACCOUNT (folder_store)) {
3594                 TnyAccount *local_account = NULL;
3595                 ModestTnyAccountStore *account_store = NULL;
3596
3597                 account_store = modest_runtime_get_account_store ();
3598                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3599
3600                 if ((gpointer) local_account != (gpointer) folder_store) {
3601                         is_local_account = FALSE;
3602                         /* New button should be dimmed on remote
3603                            account root */
3604                         new_sensitive = FALSE;
3605                 }
3606                 g_object_unref (local_account);
3607         }
3608
3609         /* Check the target folder rules */
3610         if (TNY_IS_FOLDER (folder_store)) {
3611                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3612                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3613                         ok_sensitive = FALSE;
3614                         new_sensitive = FALSE;
3615                         goto end;
3616                 }
3617         }
3618
3619         /* Check if we're moving a folder */
3620         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3621                 /* Get the widgets */
3622                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3623                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3624                 if (gtk_widget_is_focus (folder_view))
3625                         moving_folder = TRUE;
3626         }
3627
3628         if (moving_folder) {
3629                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3630
3631                 /* Get the folder to move */
3632                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3633                 
3634                 /* Check that we're not moving to the same folder */
3635                 if (TNY_IS_FOLDER (moved_folder)) {
3636                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3637                         if (parent == folder_store)
3638                                 ok_sensitive = FALSE;
3639                         g_object_unref (parent);
3640                 } 
3641
3642                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3643                         /* Do not allow to move to an account unless it's the
3644                            local folders account */
3645                         if (!is_local_account)
3646                                 ok_sensitive = FALSE;
3647                 } 
3648
3649                 if (ok_sensitive && (moved_folder == folder_store)) {
3650                         /* Do not allow to move to itself */
3651                         ok_sensitive = FALSE;
3652                 }
3653                 g_object_unref (moved_folder);
3654         } else {
3655                 TnyHeader *header = NULL;
3656                 TnyFolder *src_folder = NULL;
3657
3658                 /* Moving a message */
3659                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3660                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3661                         src_folder = tny_header_get_folder (header);
3662                         g_object_unref (header);
3663                 } else {
3664                         src_folder = 
3665                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3666                 }
3667
3668                 /* Do not allow to move the msg to the same folder */
3669                 /* Do not allow to move the msg to an account */
3670                 if ((gpointer) src_folder == (gpointer) folder_store ||
3671                     TNY_IS_ACCOUNT (folder_store))
3672                         ok_sensitive = FALSE;
3673                 g_object_unref (src_folder);
3674         }
3675
3676  end:
3677         /* Set sensitivity of the OK button */
3678         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3679         /* Set sensitivity of the NEW button */
3680         gtk_widget_set_sensitive (new_button, new_sensitive);
3681 }
3682
3683 static GtkWidget*
3684 create_move_to_dialog (GtkWindow *win,
3685                        GtkWidget *folder_view,
3686                        GtkWidget **tree_view)
3687 {
3688         GtkWidget *dialog, *scroll;
3689         GtkWidget *new_button;
3690
3691         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3692                                               GTK_WINDOW (win),
3693                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3694                                               NULL);
3695
3696         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3697         /* We do this manually so GTK+ does not associate a response ID for
3698          * the button. */
3699         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3700         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3701         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3702
3703         /* Create scrolled window */
3704         scroll = gtk_scrolled_window_new (NULL, NULL);
3705         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3706                                          GTK_POLICY_AUTOMATIC,
3707                                          GTK_POLICY_AUTOMATIC);
3708
3709         /* Create folder view */
3710         *tree_view = modest_platform_create_folder_view (NULL);
3711
3712         /* Track changes in the selection to
3713          * disable the OK button whenever "Move to" is not possible
3714          * disbale NEW button whenever New is not possible */
3715         g_signal_connect (*tree_view,
3716                           "folder_selection_changed",
3717                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3718                           win);
3719
3720         /* Listen to clicks on New button */
3721         g_signal_connect (G_OBJECT (new_button), 
3722                           "clicked", 
3723                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3724                           *tree_view);
3725
3726         /* It could happen that we're trying to move a message from a
3727            window (msg window for example) after the main window was
3728            closed, so we can not just get the model of the folder
3729            view */
3730         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3731                 const gchar *visible_id = NULL;
3732
3733                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3734                                                MODEST_FOLDER_VIEW(*tree_view));
3735
3736                 visible_id = 
3737                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3738
3739                 /* Show the same account than the one that is shown in the main window */
3740                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3741                                                                              visible_id);
3742         } else {
3743                 const gchar *active_account_name = NULL;
3744                 ModestAccountMgr *mgr = NULL;
3745                 ModestAccountData *acc_data = NULL;
3746
3747                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3748                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3749
3750                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3751                 mgr = modest_runtime_get_account_mgr ();
3752                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3753
3754                 /* Set the new visible & active account */
3755                 if (acc_data && acc_data->store_account) { 
3756                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3757                                                                                      acc_data->store_account->account_name);
3758                         modest_account_mgr_free_account_data (mgr, acc_data);
3759                 }
3760         }
3761
3762         /* Hide special folders */
3763         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3764         
3765         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3766
3767         /* Add scroll to dialog */
3768         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3769                             scroll, TRUE, TRUE, 0);
3770
3771         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3772         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3773
3774         return dialog;
3775 }
3776
3777 /*
3778  * Returns TRUE if at least one of the headers of the list belongs to
3779  * a message that has been fully retrieved.
3780  */
3781 #if 0 /* no longer in use. delete in 2007.10 */
3782 static gboolean
3783 has_retrieved_msgs (TnyList *list)
3784 {
3785         TnyIterator *iter;
3786         gboolean found = FALSE;
3787
3788         iter = tny_list_create_iterator (list);
3789         while (!tny_iterator_is_done (iter) && !found) {
3790                 TnyHeader *header;
3791                 TnyHeaderFlags flags = 0;
3792
3793                 header = TNY_HEADER (tny_iterator_get_current (iter));
3794                 if (header) {
3795                         flags = tny_header_get_flags (header);
3796                         if (flags & TNY_HEADER_FLAG_CACHED)
3797 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3798                                 found = TRUE;
3799
3800                         g_object_unref (header);
3801                 }
3802
3803                 if (!found)
3804                         tny_iterator_next (iter);
3805         }
3806         g_object_unref (iter);
3807
3808         return found;
3809 }
3810 #endif /* 0 */
3811
3812
3813 /*
3814  * Shows a confirmation dialog to the user when we're moving messages
3815  * from a remote server to the local storage. Returns the dialog
3816  * response. If it's other kind of movement then it always returns
3817  * GTK_RESPONSE_OK
3818  *
3819  * This one is used by the next functions:
3820  *      modest_ui_actions_on_paste                      - commented out
3821  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3822  */
3823 gint
3824 msgs_move_to_confirmation (GtkWindow *win,
3825                            TnyFolder *dest_folder,
3826                            gboolean delete,
3827                            TnyList *headers)
3828 {
3829         gint response = GTK_RESPONSE_OK;
3830
3831         /* return with OK if the destination is a remote folder */
3832         if (modest_tny_folder_is_remote_folder (dest_folder))
3833                 return GTK_RESPONSE_OK;
3834
3835         TnyFolder *src_folder = NULL;
3836         TnyIterator *iter = NULL;
3837         TnyHeader *header = NULL;
3838
3839         /* Get source folder */
3840         iter = tny_list_create_iterator (headers);
3841         header = TNY_HEADER (tny_iterator_get_current (iter));
3842         if (header) {
3843                 src_folder = tny_header_get_folder (header);
3844                 g_object_unref (header);
3845         }
3846         g_object_unref (iter);
3847
3848         /* if no src_folder, message may be an attahcment */
3849         if (src_folder == NULL) 
3850                 return GTK_RESPONSE_CANCEL;
3851
3852         /* If the source is a local or MMC folder */
3853         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3854                 g_object_unref (src_folder);
3855                 return GTK_RESPONSE_OK;
3856         }
3857         g_object_unref (src_folder);
3858
3859         /* now if offline we ask the user */
3860         if(connect_to_get_msg(  GTK_WINDOW (win),
3861                                         tny_list_get_length (headers)))
3862                 response = GTK_RESPONSE_OK;
3863         else
3864                 response = GTK_RESPONSE_CANCEL;
3865
3866         return response;
3867 }
3868
3869
3870
3871 static void
3872 move_to_cb (const GObject *object, gpointer user_data)
3873 {
3874         ModestMsgViewWindow *self = NULL;
3875         g_return_if_fail (GTK_IS_WIDGET (user_data));
3876         g_return_if_fail (MODEST_IS_WINDOW (object));
3877
3878         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3879                 self = MODEST_MSG_VIEW_WINDOW (object);
3880
3881                 if (!modest_msg_view_window_select_next_message (self))
3882                         if (!modest_msg_view_window_select_previous_message (self))
3883                                 /* No more messages to view, so close this window */
3884                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3885         }
3886         gtk_widget_destroy (GTK_WIDGET(user_data));
3887 }
3888
3889 void
3890 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3891                                              gpointer user_data)
3892 {
3893         ModestMainWindow *main_window = NULL;
3894         GtkWidget *folder_view = NULL;
3895         GObject *win = modest_mail_operation_get_source (mail_op);
3896         const GError *error = NULL;
3897         const gchar *message = NULL;
3898         
3899         /* Get error message */
3900         error = modest_mail_operation_get_error (mail_op);
3901         if (error != NULL && error->message != NULL) {
3902                 message = error->message;
3903         } else {
3904                 message = _("mail_in_ui_folder_move_target_error");
3905         }
3906         
3907         /* Disable next automatic folder selection */
3908         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3909                 main_window = MODEST_MAIN_WINDOW(user_data);
3910                 folder_view = modest_main_window_get_child_widget (main_window,
3911                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);     
3912                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));             
3913         }
3914
3915         /* Show notification dialog */
3916         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3917         g_object_unref (win);
3918 }
3919
3920 void
3921 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3922                                               gpointer user_data)
3923 {
3924         GObject *win = modest_mail_operation_get_source (mail_op);
3925         const GError *error = modest_mail_operation_get_error (mail_op);
3926
3927         g_return_if_fail (error != NULL);
3928         if (error->message != NULL)             
3929                 g_printerr ("modest: %s\n", error->message);
3930         else
3931                 g_printerr ("modest: unkonw error on send&receive operation");
3932
3933         /* Show error message */
3934 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3935 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3936 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3937 /*      else  */
3938 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3939 /*                                                      _CS("sfil_ib_unable_to_send")); */
3940         g_object_unref (win);
3941 }
3942
3943 static void
3944 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3945                        TnyHeader *header, 
3946                        TnyMsg *msg, 
3947                        gpointer user_data)
3948 {
3949         TnyList *parts;
3950         TnyIterator *iter;
3951         gint pending_purges = 0;
3952         gboolean some_purged = FALSE;
3953         ModestWindow *win = MODEST_WINDOW (user_data);
3954         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3955
3956         /* If there was any error */
3957         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3958                 modest_window_mgr_unregister_header (mgr, header);
3959                 return;
3960         }
3961
3962         /* Once the message has been retrieved for purging, we check if
3963          * it's all ok for purging */
3964
3965         parts = tny_simple_list_new ();
3966         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3967         iter = tny_list_create_iterator (parts);
3968
3969         while (!tny_iterator_is_done (iter)) {
3970                 TnyMimePart *part;
3971                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3972                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3973                         if (tny_mime_part_is_purged (part))
3974                                 some_purged = TRUE;
3975                         else
3976                                 pending_purges++;
3977                 }
3978
3979                 if (part)
3980                         g_object_unref (part);
3981
3982                 tny_iterator_next (iter);
3983         }
3984
3985         if (pending_purges>0) {
3986                 gint response;
3987                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3988
3989                 if (response == GTK_RESPONSE_OK) {
3990                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3991                         tny_iterator_first (iter);
3992                         while (!tny_iterator_is_done (iter)) {
3993                                 TnyMimePart *part;
3994                                 
3995                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3996                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3997                                         tny_mime_part_set_purged (part);
3998
3999                                 if (part)
4000                                         g_object_unref (part);
4001
4002                                 tny_iterator_next (iter);
4003                         }
4004                         
4005                         tny_msg_rewrite_cache (msg);
4006                 }
4007         } else {
4008                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4009         }
4010
4011         /* remove attachments */
4012         tny_iterator_first (iter);
4013         while (!tny_iterator_is_done (iter)) {
4014                 TnyMimePart *part;
4015                         
4016                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4017                 if (part) {
4018                         /* One for the reference given by tny_iterator_get_current(): */
4019                         g_object_unref (part);
4020
4021                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
4022                          * Otherwise, this seems useless. */
4023                 }
4024
4025                 tny_iterator_next (iter);
4026         }
4027         modest_window_mgr_unregister_header (mgr, header);
4028
4029         g_object_unref (iter);
4030         g_object_unref (parts);
4031 }
4032
4033 static void
4034 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4035                                                      ModestMainWindow *win)
4036 {
4037         GtkWidget *header_view;
4038         TnyList *header_list;
4039         TnyIterator *iter;
4040         TnyHeader *header;
4041         TnyHeaderFlags flags;
4042         ModestWindow *msg_view_window =  NULL;
4043         gboolean found;
4044
4045         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4046
4047         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4048                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
4049
4050         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4051
4052         if (tny_list_get_length (header_list) == 1) {
4053                 iter = tny_list_create_iterator (header_list);
4054                 header = TNY_HEADER (tny_iterator_get_current (iter));
4055                 g_object_unref (iter);
4056         } else {
4057                 return;
4058         }
4059
4060         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4061                                                           header, &msg_view_window);
4062         flags = tny_header_get_flags (header);
4063         if (!(flags & TNY_HEADER_FLAG_CACHED))
4064                 return;
4065         if (found) {
4066                 if (msg_view_window != NULL) 
4067                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4068                 else {
4069                         /* do nothing; uid was registered before, so window is probably on it's way */
4070                         g_warning ("debug: header %p has already been registered", header);
4071                 }
4072         } else {
4073                 ModestMailOperation *mail_op = NULL;
4074                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4075                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4076                                                                          G_OBJECT (win),
4077                                                                          modest_ui_actions_get_msgs_full_error_handler,
4078                                                                          NULL);
4079                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4080                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4081                 
4082                 g_object_unref (mail_op);
4083         }
4084         if (header)
4085                 g_object_unref (header);
4086         if (header_list)
4087                 g_object_unref (header_list);
4088 }
4089
4090 /**
4091  * Utility function that transfer messages from both the main window
4092  * and the msg view window when using the "Move to" dialog
4093  */
4094 static void
4095 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4096                                               ModestWindow *win)
4097 {
4098         TnyList *headers = NULL;
4099         TnyAccount *dst_account = NULL;
4100         const gchar *proto_str = NULL;
4101         gboolean dst_is_pop = FALSE;
4102
4103         if (!TNY_IS_FOLDER (dst_folder)) {
4104                 modest_platform_information_banner (GTK_WIDGET (win),
4105                                                     NULL,
4106                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4107                 return;
4108         }
4109
4110         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4111         proto_str = tny_account_get_proto (dst_account);
4112
4113         /* tinymail will return NULL for local folders it seems */
4114         dst_is_pop = proto_str &&
4115                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4116                  MODEST_PROTOCOL_STORE_POP);
4117
4118         g_object_unref (dst_account);
4119
4120         /* Get selected headers */
4121         headers = get_selected_headers (MODEST_WINDOW (win));
4122
4123         if (dst_is_pop) {
4124                 modest_platform_information_banner (GTK_WIDGET (win),
4125                                                     NULL,
4126                                                     ngettext("mail_in_ui_folder_move_target_error",
4127                                                              "mail_in_ui_folder_move_targets_error",
4128                                                              tny_list_get_length (headers)));
4129                 g_object_unref (headers);
4130                 return;
4131         }
4132
4133         GtkWidget *inf_note;
4134         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4135                                                      _CS("ckct_nw_pasting"));
4136         if (inf_note != NULL)  {
4137                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4138                 gtk_widget_show (GTK_WIDGET(inf_note));
4139         }
4140
4141         ModestMailOperation *mail_op = 
4142                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4143                                                                G_OBJECT(win),
4144                                                                modest_ui_actions_move_folder_error_handler,
4145                                                                NULL);
4146         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4147                                          mail_op);
4148
4149         modest_mail_operation_xfer_msgs (mail_op, 
4150                                          headers,
4151                                          TNY_FOLDER (dst_folder),
4152                                          TRUE,
4153                                          move_to_cb,
4154                                          inf_note);
4155
4156         g_object_unref (G_OBJECT (mail_op));
4157         g_object_unref (headers);
4158 }
4159
4160 /*
4161  * UI handler for the "Move to" action when invoked from the
4162  * ModestMainWindow
4163  */
4164 static void 
4165 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4166                                           GtkWidget *folder_view,
4167                                           TnyFolderStore *dst_folder,
4168                                           ModestMainWindow *win)
4169 {
4170         ModestHeaderView *header_view = NULL;
4171         ModestMailOperation *mail_op = NULL;
4172         TnyFolderStore *src_folder;
4173         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4174
4175         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4176
4177         /* Get the source folder */
4178         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4179
4180         /* Get header view */
4181         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW));
4182
4183         /* Get folder or messages to transfer */
4184         if (gtk_widget_is_focus (folder_view)) {
4185                 GtkTreeSelection *sel;
4186                 gboolean do_xfer = TRUE;
4187
4188                 /* Allow only to transfer folders to the local root folder */
4189                 if (TNY_IS_ACCOUNT (dst_folder) && 
4190                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4191                         do_xfer = FALSE;
4192                 } else if (!TNY_IS_FOLDER (src_folder)) {
4193                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4194                         do_xfer = FALSE;
4195                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4196                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4197                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4198                                 do_xfer = FALSE;
4199                         }
4200                 }
4201
4202                 if (do_xfer) {
4203                         GtkWidget *inf_note;
4204                         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4205                                                                      _CS("ckct_nw_pasting"));
4206                         if (inf_note != NULL)  {
4207                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4208                                 gtk_widget_show (GTK_WIDGET(inf_note));
4209                         }
4210                         /* Clean folder on header view before moving it */
4211                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4212                         gtk_tree_selection_unselect_all (sel);
4213
4214                         mail_op =
4215                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4216                                                                          G_OBJECT(win),
4217                                                                          modest_ui_actions_move_folder_error_handler,
4218                                                                          win);
4219                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4220                                                          mail_op);
4221
4222                         /* Select *after* the changes */
4223                         /* TODO: this function hangs UI after transfer */ 
4224 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4225 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4226                         
4227                         modest_mail_operation_xfer_folder (mail_op,
4228                                                            TNY_FOLDER (src_folder),
4229                                                            dst_folder,
4230                                                            TRUE, move_to_cb, inf_note);
4231                         /* Unref mail operation */
4232                         g_object_unref (G_OBJECT (mail_op));
4233                 }
4234         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4235                 gboolean do_xfer = TRUE;
4236                 /* Ask for confirmation if the source folder is remote and we're not connected */
4237                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4238                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4239                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4240                                 guint num_headers = tny_list_get_length(headers);
4241                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4242                                         do_xfer = FALSE;
4243                                 }
4244                         }
4245                         g_object_unref(headers);
4246                 }
4247                 if (do_xfer) /* Transfer messages */
4248                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4249         }
4250
4251     if (src_folder)
4252         g_object_unref (src_folder);
4253 }
4254
4255
4256 /*
4257  * UI handler for the "Move to" action when invoked from the
4258  * ModestMsgViewWindow
4259  */
4260 static void 
4261 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4262                                               TnyFolderStore *dst_folder,
4263                                               ModestMsgViewWindow *win)
4264 {
4265         TnyHeader *header = NULL;
4266         TnyFolderStore *src_folder;
4267
4268         /* Create header list */
4269         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4270         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4271         g_object_unref (header);
4272
4273         /* Transfer the message if online or confirmed by the user */
4274         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4275             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4276                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4277         }
4278
4279         g_object_unref (src_folder);
4280 }
4281
4282 void 
4283 modest_ui_actions_on_move_to (GtkAction *action, 
4284                               ModestWindow *win)
4285 {
4286         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4287         gint result = 0;
4288         TnyFolderStore *dst_folder = NULL;
4289         ModestMainWindow *main_window;
4290
4291         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4292                           MODEST_IS_MSG_VIEW_WINDOW (win));
4293
4294         /* Get the main window if exists */
4295         if (MODEST_IS_MAIN_WINDOW (win))
4296                 main_window = MODEST_MAIN_WINDOW (win);
4297         else
4298                 main_window = 
4299                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4300
4301         /* Get the folder view widget if exists */
4302         if (main_window)
4303                 folder_view = modest_main_window_get_child_widget (main_window,
4304                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
4305         else
4306                 folder_view = NULL;
4307
4308         /* Create and run the dialog */
4309         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4310         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4311         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4312         result = gtk_dialog_run (GTK_DIALOG(dialog));
4313         g_object_ref (tree_view);
4314         gtk_widget_destroy (dialog);
4315
4316         if (result != GTK_RESPONSE_ACCEPT)
4317                 return;
4318
4319         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4320         /* Do window specific stuff */
4321         if (MODEST_IS_MAIN_WINDOW (win)) {
4322                 modest_ui_actions_on_main_window_move_to (action,
4323                                                           folder_view,
4324                                                           dst_folder,
4325                                                           MODEST_MAIN_WINDOW (win));
4326         } else {
4327                 modest_ui_actions_on_msg_view_window_move_to (action,
4328                                                               dst_folder,
4329                                                               MODEST_MSG_VIEW_WINDOW (win));
4330         }
4331
4332         if (dst_folder)
4333                 g_object_unref (dst_folder);
4334 }
4335
4336 /*
4337  * Calls #HeadersFunc for each header already selected in the main
4338  * window or the message currently being shown in the msg view window
4339  */
4340 static void
4341 do_headers_action (ModestWindow *win, 
4342                    HeadersFunc func,
4343                    gpointer user_data)
4344 {
4345         TnyList *headers_list = NULL;
4346         TnyIterator *iter = NULL;
4347         TnyHeader *header = NULL;
4348         TnyFolder *folder = NULL;
4349
4350         /* Get headers */
4351         headers_list = get_selected_headers (win);
4352         if (!headers_list)
4353                 return;
4354
4355         /* Get the folder */
4356         iter = tny_list_create_iterator (headers_list);
4357         header = TNY_HEADER (tny_iterator_get_current (iter));
4358         if (header) {
4359                 folder = tny_header_get_folder (header);
4360                 g_object_unref (header);
4361         }
4362
4363         /* Call the function for each header */
4364         while (!tny_iterator_is_done (iter)) {
4365                 header = TNY_HEADER (tny_iterator_get_current (iter));
4366                 func (header, win, user_data);
4367                 g_object_unref (header);
4368                 tny_iterator_next (iter);
4369         }
4370
4371         /* Trick: do a poke status in order to speed up the signaling
4372            of observers */
4373         tny_folder_poke_status (folder);
4374
4375         /* Frees */
4376         g_object_unref (folder);
4377         g_object_unref (iter);
4378         g_object_unref (headers_list);
4379 }
4380
4381 void 
4382 modest_ui_actions_view_attachment (GtkAction *action,
4383                                    ModestWindow *window)
4384 {
4385         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4386                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4387         } else {
4388                 /* not supported window for this action */
4389                 g_return_if_reached ();
4390         }
4391 }
4392
4393 void
4394 modest_ui_actions_save_attachments (GtkAction *action,
4395                                     ModestWindow *window)
4396 {
4397         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4398                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4399         } else {
4400                 /* not supported window for this action */
4401                 g_return_if_reached ();
4402         }
4403 }
4404
4405 void
4406 modest_ui_actions_remove_attachments (GtkAction *action,
4407                                       ModestWindow *window)
4408 {
4409         if (MODEST_IS_MAIN_WINDOW (window)) {
4410                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4411         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4412                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4413         } else {
4414                 /* not supported window for this action */
4415                 g_return_if_reached ();
4416         }
4417 }
4418
4419 void 
4420 modest_ui_actions_on_settings (GtkAction *action, 
4421                                ModestWindow *win)
4422 {
4423         GtkWidget *dialog;
4424
4425         dialog = modest_platform_get_global_settings_dialog ();
4426         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4427         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4428         gtk_widget_show_all (dialog);
4429
4430         gtk_dialog_run (GTK_DIALOG (dialog));
4431
4432         gtk_widget_destroy (dialog);
4433 }
4434
4435 void 
4436 modest_ui_actions_on_help (GtkAction *action, 
4437                            ModestWindow *win)
4438 {
4439         const gchar *help_id = NULL;
4440
4441         if (MODEST_IS_MAIN_WINDOW (win)) {
4442                 GtkWidget *folder_view;
4443                 TnyFolderStore *folder_store;
4444                 
4445                 /* Get selected folder */
4446                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4447                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
4448                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4449
4450                 /* Switch help_id */
4451                 if (TNY_IS_FOLDER (folder_store)) {
4452                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4453                         case TNY_FOLDER_TYPE_NORMAL:
4454                                 help_id = "applications_email_managefolders";
4455                                 break;
4456                         case TNY_FOLDER_TYPE_INBOX:
4457                                 help_id = "applications_email_inbox";
4458                                 break;
4459                         case TNY_FOLDER_TYPE_OUTBOX:
4460                                 help_id = "applications_email_outbox";
4461                                 break;
4462                         case TNY_FOLDER_TYPE_SENT:
4463                                 help_id = "applications_email_sent";
4464                                 break;
4465                         case TNY_FOLDER_TYPE_DRAFTS:
4466                                 help_id = "applications_email_drafts";
4467                                 break;
4468                         case TNY_FOLDER_TYPE_ARCHIVE:
4469                                 help_id = "applications_email_managefolders";
4470                                 break;
4471                         default:
4472                                 help_id = "applications_email_managefolders";
4473                         }
4474                 } else {
4475                         help_id = "applications_email_mainview";
4476                 }
4477                 g_object_unref (folder_store);
4478         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4479                 help_id = "applications_email_viewer";
4480         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4481                 help_id = "applications_email_editor";
4482
4483         modest_platform_show_help (GTK_WINDOW (win), help_id);
4484 }
4485
4486 void 
4487 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4488                                             ModestWindow *window)
4489 {
4490         ModestMailOperation *mail_op;
4491         TnyList *headers;
4492
4493         /* Get headers */
4494         headers = get_selected_headers (window);
4495         if (!headers)
4496                 return;
4497
4498         /* Create mail operation */
4499         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4500                                                                  G_OBJECT (window),
4501                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4502                                                                  NULL);
4503         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4504         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4505
4506         /* Frees */
4507         g_object_unref (headers);
4508         g_object_unref (mail_op);
4509 }
4510
4511 void
4512 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4513                                           ModestWindow *window)
4514 {
4515         g_return_if_fail (MODEST_IS_WINDOW (window));
4516         
4517         /* Update dimmed */     
4518         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4519 }
4520
4521 void
4522 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4523                                           ModestWindow *window)
4524 {
4525         g_return_if_fail (MODEST_IS_WINDOW (window));
4526
4527         /* Update dimmed */     
4528         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4529 }
4530
4531 void
4532 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4533                                           ModestWindow *window)
4534 {
4535         g_return_if_fail (MODEST_IS_WINDOW (window));
4536
4537         /* Update dimmed */     
4538         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4539 }
4540
4541 void
4542 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4543                                           ModestWindow *window)
4544 {
4545         g_return_if_fail (MODEST_IS_WINDOW (window));
4546
4547         /* Update dimmed */     
4548         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4549 }
4550
4551 void
4552 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4553                                           ModestWindow *window)
4554 {
4555         g_return_if_fail (MODEST_IS_WINDOW (window));
4556
4557         /* Update dimmed */     
4558         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4559 }
4560
4561 void
4562 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4563                                                  ModestWindow *window)
4564 {
4565         g_return_if_fail (MODEST_IS_WINDOW (window));
4566
4567         /* Update dimmed */     
4568         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4569 }
4570
4571 void
4572 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4573                                                      ModestWindow *window)
4574 {
4575         g_return_if_fail (MODEST_IS_WINDOW (window));
4576
4577         /* Update dimmed */     
4578         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4579 }
4580
4581 void
4582 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4583                                                      ModestWindow *window)
4584 {
4585         g_return_if_fail (MODEST_IS_WINDOW (window));
4586
4587         /* Update dimmed */     
4588         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4589 }
4590
4591 void
4592 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4593 {
4594         g_return_if_fail (MODEST_IS_WINDOW (window));
4595
4596         /* Update dimmed */     
4597         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4598 }
4599
4600 void
4601 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4602 {
4603         g_return_if_fail (MODEST_IS_WINDOW (window));
4604
4605         modest_platform_show_search_messages (GTK_WINDOW (window));
4606 }
4607
4608 void     
4609 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4610 {
4611         g_return_if_fail (MODEST_IS_WINDOW (win));
4612         modest_platform_show_addressbook (GTK_WINDOW (win));
4613 }
4614
4615
4616 void
4617 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4618                                           ModestWindow *window)
4619 {
4620         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4621
4622         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4623 }
4624
4625 static void 
4626 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4627                                    ModestMailOperationState *state,
4628                                    gpointer user_data)
4629 {
4630         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4631
4632         /* Set send/receive operation finished */       
4633         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4634                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4635         
4636 }
4637
4638