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