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