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