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