* Add a error_handler for send_receive operation.
[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
49 #ifdef MODEST_PLATFORM_MAEMO
50 #include "maemo/modest-osso-state-saving.h"
51 #endif /* MODEST_PLATFORM_MAEMO */
52
53 #include "widgets/modest-ui-constants.h"
54 #include <widgets/modest-main-window.h>
55 #include <widgets/modest-msg-view-window.h>
56 #include <widgets/modest-account-view-window.h>
57 #include <widgets/modest-details-dialog.h>
58 #include <widgets/modest-attachments-view.h>
59 #include "widgets/modest-folder-view.h"
60 #include "widgets/modest-global-settings-dialog.h"
61 #include "modest-connection-specific-smtp-window.h"
62 #include "modest-account-mgr-helpers.h"
63 #include "modest-mail-operation.h"
64 #include "modest-text-utils.h"
65
66 #ifdef MODEST_HAVE_EASYSETUP
67 #include "easysetup/modest-easysetup-wizard.h"
68 #endif /* MODEST_HAVE_EASYSETUP */
69
70 #include <modest-widget-memory.h>
71 #include <tny-error.h>
72 #include <tny-simple-list.h>
73 #include <tny-msg-view.h>
74 #include <tny-device.h>
75 #include <tny-merge-folder.h>
76
77 #include <gtkhtml/gtkhtml.h>
78
79 typedef struct _GetMsgAsyncHelper {     
80         ModestWindow *window;
81         ModestMailOperation *mail_op;
82         TnyIterator *iter;
83         guint num_ops;
84         GFunc func;     
85         gpointer user_data;
86 } GetMsgAsyncHelper;
87
88 typedef enum _ReplyForwardAction {
89         ACTION_REPLY,
90         ACTION_REPLY_TO_ALL,
91         ACTION_FORWARD
92 } ReplyForwardAction;
93
94 typedef struct _ReplyForwardHelper {
95         guint reply_forward_type;
96         ReplyForwardAction action;
97         gchar *account_name;
98         GtkWidget *parent_window;
99 } ReplyForwardHelper;
100
101
102 /*
103  * The do_headers_action uses this kind of functions to perform some
104  * action to each member of a list of headers
105  */
106 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
107
108 static void
109 do_headers_action (ModestWindow *win, 
110                    HeadersFunc func,
111                    gpointer user_data);
112
113
114 static void     open_msg_cb            (ModestMailOperation *mail_op, 
115                                         TnyHeader *header, 
116                                         TnyMsg *msg,
117                                         gpointer user_data);
118
119 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
120                                         TnyHeader *header, 
121                                         TnyMsg *msg,
122                                         gpointer user_data);
123
124 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
125
126
127 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
128                                                    ModestMailOperationState *state,
129                                                    gpointer user_data);
130
131
132
133 static void
134 run_account_setup_wizard (ModestWindow *win)
135 {
136         ModestEasysetupWizardDialog *wizard;
137
138         g_return_if_fail (MODEST_IS_WINDOW(win));
139         
140         wizard = modest_easysetup_wizard_dialog_new ();
141         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
142         gtk_dialog_run (GTK_DIALOG (wizard));
143         gtk_widget_destroy (GTK_WIDGET (wizard));
144 }
145
146
147 void   
148 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
149 {
150         GtkWidget *about;
151         const gchar *authors[] = {
152                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
153                 NULL
154         };
155         about = gtk_about_dialog_new ();
156         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
157         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
158         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
159                                         _("Copyright (c) 2006, Nokia Corporation\n"
160                                           "All rights reserved."));
161         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
162                                        _("a modest e-mail client\n\n"
163                                          "design and implementation: Dirk-Jan C. Binnema\n"
164                                          "contributions from the fine people at KC and Ig\n"
165                                          "uses the tinymail email framework written by Philip van Hoof"));
166         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
167         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
168         
169         gtk_dialog_run (GTK_DIALOG (about));
170         gtk_widget_destroy(about);
171 }
172
173 /*
174  * Gets the list of currently selected messages. If the win is the
175  * main window, then it returns a newly allocated list of the headers
176  * selected in the header view. If win is the msg view window, then
177  * the value returned is a list with just a single header.
178  *
179  * The caller of this funcion must free the list.
180  */
181 static TnyList *
182 get_selected_headers (ModestWindow *win)
183 {
184         if (MODEST_IS_MAIN_WINDOW(win)) {
185                 GtkWidget *header_view;         
186                 
187                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
188                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
189                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
190                 
191         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
192                 /* for MsgViewWindows, we simply return a list with one element */
193                 TnyHeader *header;
194                 TnyList *list = NULL;
195                 
196                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
197                 if (header != NULL) {
198                         list = tny_simple_list_new ();
199                         tny_list_prepend (list, G_OBJECT(header));
200                         g_object_unref (G_OBJECT(header));
201                 }
202
203                 return list;
204
205         } else
206                 return NULL;
207 }
208
209 static void
210 headers_action_mark_as_read (TnyHeader *header,
211                              ModestWindow *win,
212                              gpointer user_data)
213 {
214         TnyHeaderFlags flags;
215
216         g_return_if_fail (TNY_IS_HEADER(header));
217
218         flags = tny_header_get_flags (header);
219         if (flags & TNY_HEADER_FLAG_SEEN) return;
220         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
221 }
222
223 static void
224 headers_action_mark_as_unread (TnyHeader *header,
225                                ModestWindow *win,
226                                gpointer user_data)
227 {
228         TnyHeaderFlags flags;
229
230         g_return_if_fail (TNY_IS_HEADER(header));
231
232         flags = tny_header_get_flags (header);
233         if (flags & TNY_HEADER_FLAG_SEEN)  {
234                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
235         }
236 }
237
238
239 static void
240 headers_action_delete (TnyHeader *header,
241                        ModestWindow *win,
242                        gpointer user_data)
243 {
244         ModestMailOperation *mail_op = NULL;
245
246         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
247         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
248                                          mail_op);
249         
250         /* Always delete. TODO: Move to trash still not supported */
251         modest_mail_operation_remove_msg (mail_op, header, FALSE);
252         g_object_unref (G_OBJECT (mail_op));
253 }
254
255 void
256 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
257 {
258         TnyList *header_list = NULL;
259         TnyIterator *iter = NULL;
260         TnyHeader *header = NULL;
261         gchar *message = NULL;
262         gchar *desc = NULL;
263         gint response;
264         gboolean found;
265         ModestWindowMgr *mgr;
266         GtkWidget *header_view;
267
268         g_return_if_fail (MODEST_IS_WINDOW(win));
269
270         /* Check first if the header view has the focus */
271         if (MODEST_IS_MAIN_WINDOW (win)) {
272                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
273                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
274                 if (!gtk_widget_is_focus (header_view))
275                         return;
276         }
277
278         header_list = get_selected_headers (win);
279         if (!header_list) return;
280
281         /* Check if any of the headers is already opened, or in the process of being opened */
282         iter = tny_list_create_iterator (header_list);
283         found = FALSE;
284         mgr = modest_runtime_get_window_mgr ();
285         while (!tny_iterator_is_done (iter) && !found) {
286                 header = TNY_HEADER (tny_iterator_get_current (iter));
287                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
288                 g_object_unref (header);
289                 tny_iterator_next (iter);
290         }
291         g_object_unref (iter);
292
293         if (found) {
294                 gchar *num, *msg;
295
296                 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
297                 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
298
299                 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
300
301                 g_free (msg);
302                 g_free (num);
303                 g_object_unref (header_list);
304                 return;
305         }
306
307         /* Select message */
308         if (tny_list_get_length(header_list) == 1) {
309                 iter = tny_list_create_iterator (header_list);
310                 header = TNY_HEADER (tny_iterator_get_current (iter));
311                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
312                 g_object_unref (header);
313                 g_object_unref (iter);
314         }
315         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
316                                            tny_list_get_length(header_list)), desc);
317
318         /* Confirmation dialog */               
319         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
320                                                             message);
321         
322
323         if (response == GTK_RESPONSE_OK) {
324                 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
325                         gboolean ret_value;
326                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
327                         return;
328                 }
329                 
330                 /* Remove each header */
331                 do_headers_action (win, headers_action_delete, NULL);
332
333                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
334                         gtk_widget_destroy (GTK_WIDGET(win));
335                 } 
336         }
337
338         /* Update toolbar dimming state */
339         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (win));
340
341         /* free */
342         g_free(message);
343         g_free(desc);
344         g_object_unref (header_list);
345 }
346
347
348 void
349 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
350 {
351 #ifdef MODEST_PLATFORM_MAEMO
352         modest_osso_save_state();
353 #endif /* MODEST_PLATFORM_MAEMO */
354
355         /* FIXME: we need to cancel all actions/threads here,
356          so we really quit */
357
358         gtk_main_quit ();
359 }
360
361 void
362 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
363 {
364         gboolean ret_value;
365         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
366
367 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
368 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
369 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
370 /*              gboolean ret_value; */
371 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
372 /*      } else if (MODEST_IS_WINDOW (win)) { */
373 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
374 /*      } else { */
375 /*              g_return_if_reached (); */
376 /*      } */
377 }
378
379 void
380 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
381 {
382         GtkClipboard *clipboard = NULL;
383         gchar *selection = NULL;
384
385         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
386         selection = gtk_clipboard_wait_for_text (clipboard);
387
388         /* Question: why is the clipboard being used here? 
389          * It doesn't really make a lot of sense. */
390
391         if (selection)
392         {
393                 modest_address_book_add_address (selection);
394                 g_free (selection);
395         }
396 }
397
398 void
399 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
400 {
401         /* This is currently only implemented for Maemo */
402 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
403         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
404                 run_account_setup_wizard (win);
405                 return;
406         } else  {
407                 /* Show the list of accounts: */
408                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
409                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
410                 gtk_dialog_run (account_win);
411                 gtk_widget_destroy (GTK_WIDGET(account_win));
412         }
413 #else
414         GtkWidget *dialog, *label;
415         
416         /* Create the widgets */
417         
418         dialog = gtk_dialog_new_with_buttons ("Message",
419                                               GTK_WINDOW(win),
420                                               GTK_DIALOG_DESTROY_WITH_PARENT,
421                                               GTK_STOCK_OK,
422                                               GTK_RESPONSE_NONE,
423                                               NULL);
424         label = gtk_label_new ("Hello World!");
425         
426         /* Ensure that the dialog box is destroyed when the user responds. */
427         
428         g_signal_connect_swapped (dialog, "response", 
429                                   G_CALLBACK (gtk_widget_destroy),
430                                   dialog);
431         
432         /* Add the label, and show everything we've added to the dialog. */
433         
434         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
435                            label);
436         gtk_widget_show_all (dialog);
437 #endif /* MODEST_PLATFORM_MAEMO */
438 }
439
440 static void
441 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
442 {
443         ModestWindow *main_window = MODEST_WINDOW (user_data);
444         
445         /* Save any changes. */
446         modest_connection_specific_smtp_window_save_server_accounts (
447                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
448                         modest_window_get_active_account (main_window));
449         gtk_widget_destroy (GTK_WIDGET (window));
450 }
451
452
453
454 void
455 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
456 {
457         /* This is currently only implemented for Maemo,
458          * because it requires an API (libconic) to detect different connection 
459          * possiblities.
460          */
461 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
462         
463         /* Create the window if necessary: */
464         const gchar *active_account_name = modest_window_get_active_account (win);
465         
466         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
467          * or show the default account?
468          * If we show the default account then the account name should be shown in 
469          * the window when we show it. */
470         if (!active_account_name) {
471                 g_warning ("%s: No account is active.", __FUNCTION__);
472                 return;
473         }
474                 
475         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
476         modest_connection_specific_smtp_window_fill_with_connections (
477                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
478                 modest_runtime_get_account_mgr(), 
479                 active_account_name);
480
481         /* Show the window: */  
482         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
483         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
484         gtk_widget_show (specific_window);
485     
486         /* Save changes when the window is hidden: */
487         g_signal_connect (specific_window, "hide", 
488                 G_CALLBACK (on_smtp_servers_window_hide), win);
489 #endif /* MODEST_PLATFORM_MAEMO */
490 }
491
492 void
493 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
494 {
495         ModestWindow *msg_win = NULL;
496         TnyMsg *msg = NULL;
497         TnyFolder *folder = NULL;
498         gchar *account_name = NULL;
499         gchar *from_str = NULL;
500 /*      GError *err = NULL; */
501         TnyAccount *account = NULL;
502         ModestWindowMgr *mgr;
503         gchar *signature = NULL, *blank_and_signature = NULL;
504
505         /* if there are no accounts yet, just show the wizard */
506         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
507                         run_account_setup_wizard (win);
508                         return;
509         }
510         
511         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
512         if (!account_name)
513                 account_name = g_strdup (modest_window_get_active_account (win));
514         if (!account_name) {
515                 g_printerr ("modest: no account found\n");
516                 goto cleanup;
517         }
518         
519         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
520                                                                        account_name,
521                                                                        TNY_ACCOUNT_TYPE_STORE);
522         if (!account) {
523                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
524                 goto cleanup;
525         }
526
527         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
528         if (!from_str) {
529                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
530                 goto cleanup;
531         }
532
533         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
534                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
535                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
536                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
537                 blank_and_signature = g_strconcat ("\n", signature, NULL);
538                 g_free (signature);
539         } else {
540                 blank_and_signature = g_strdup ("");
541         }
542
543         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
544         if (!msg) {
545                 g_printerr ("modest: failed to create new msg\n");
546                 goto cleanup;
547         }
548         
549         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
550         if (!folder) {
551                 g_printerr ("modest: failed to find Drafts folder\n");
552                 goto cleanup;
553         }
554         
555
556         /* Create and register edit window */
557         /* This is destroyed by TOOD. */
558         msg_win = modest_msg_edit_window_new (msg, account_name);
559         mgr = modest_runtime_get_window_mgr ();
560         modest_window_mgr_register_window (mgr, msg_win);
561
562         if (win)
563                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
564                                               GTK_WINDOW (win));        
565         gtk_widget_show_all (GTK_WIDGET (msg_win));
566
567 cleanup:
568         g_free (account_name);
569         g_free (from_str);
570         g_free (blank_and_signature);
571         if (msg_win)
572                 g_object_unref (msg_win);
573         if (account)
574                 g_object_unref (G_OBJECT(account));
575         if (msg)
576                 g_object_unref (G_OBJECT(msg));
577         if (folder)
578                 g_object_unref (G_OBJECT(folder));
579 }
580
581 static void
582 open_msg_cb (ModestMailOperation *mail_op, 
583              TnyHeader *header, 
584              TnyMsg *msg, 
585              gpointer user_data)
586 {
587         ModestWindowMgr *mgr = NULL;
588         ModestWindow *parent_win = NULL;
589         ModestWindow *win = NULL;
590         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
591         gchar *account = NULL;
592         TnyFolder *folder;
593         
594         /* TODO: Show an error? (review the specs) */
595         if (!msg)
596                 return;
597
598         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
599         folder = tny_header_get_folder (header);
600
601         /* Mark header as read */
602         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
603
604         /* Get account */
605         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
606         if (!account)
607                 account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
608         
609         /* Gets folder type (OUTBOX headers will be opened in edit window */
610         if (modest_tny_folder_is_local_folder (folder))
611                 folder_type = modest_tny_folder_get_local_folder_type (folder);
612
613         /* If the header is in the drafts folder then open the editor,
614            else the message view window */
615         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
616                 /* we cannot edit without a valid account... */
617                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
618                         run_account_setup_wizard(parent_win);
619                         goto cleanup;
620                 }
621                 win = modest_msg_edit_window_new (msg, account);
622         } else {
623                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
624                 
625                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
626                         GtkWidget *header_view;
627                         GtkTreeSelection *sel;
628                         GList *sel_list = NULL;
629                         GtkTreeModel *model;
630                         
631                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
632                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
633
634                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
635                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
636
637                         if (sel_list != NULL) {
638                                 GtkTreeRowReference *row_reference;
639
640                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
641                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
642                                 g_list_free (sel_list);
643                                 
644                                 win = modest_msg_view_window_new_with_header_model (msg, 
645                                                                                     account,
646                                                                                     (const gchar*) uid,
647                                                                                     model, 
648                                                                                     row_reference);
649                                 gtk_tree_row_reference_free (row_reference);
650                         } else {
651                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
652                         }
653                 } else {
654                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
655                 }
656                 g_free (uid);
657         }
658         
659         /* Register and show new window */
660         if (win != NULL) {
661                 mgr = modest_runtime_get_window_mgr ();
662                 modest_window_mgr_register_window (mgr, win);
663                 g_object_unref (win);
664                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
665                 gtk_widget_show_all (GTK_WIDGET(win));
666         }
667
668         /* Update toolbar dimming state */
669         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
670                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
671         }
672
673 cleanup:
674         /* Free */
675         g_free(account);
676         g_object_unref (parent_win);
677 /*      g_object_unref (msg); */
678         g_object_unref (folder);
679 }
680
681 /*
682  * This function is the error handler of the
683  * modest_mail_operation_get_msgs_full operation
684  */
685 static void
686 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
687                                                gpointer user_data)
688 {
689         const GError *error;
690
691         error = modest_mail_operation_get_error (mail_op);
692         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
693                 GObject *win = modest_mail_operation_get_source (mail_op);
694
695                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
696                                                         error->message);
697                 g_object_unref (win);
698         }
699 }
700
701 /*
702  * This function is used by both modest_ui_actions_on_open and
703  * modest_ui_actions_on_header_activated. This way we always do the
704  * same when trying to open messages.
705  */
706 static void
707 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
708 {
709         ModestWindowMgr *mgr = NULL;
710         TnyIterator *iter = NULL;
711         ModestMailOperation *mail_op1 = NULL;
712         ModestMailOperation *mail_op2 = NULL;
713         TnyList *not_opened_headers = NULL;
714         TnyList *not_opened_cached_headers = NULL;
715         TnyHeaderFlags flags;
716                 
717         /* Look if we already have a message view for each header. If
718            true, then remove the header from the list of headers to
719            open */
720         mgr = modest_runtime_get_window_mgr ();
721         iter = tny_list_create_iterator (headers);
722         not_opened_headers = tny_simple_list_new ();
723         not_opened_cached_headers = tny_simple_list_new ();
724         while (!tny_iterator_is_done (iter)) {
725
726                 ModestWindow *window;
727                 TnyHeader *header;
728                 gboolean found;
729                 
730                 header = TNY_HEADER (tny_iterator_get_current (iter));
731                 flags = tny_header_get_flags (header);
732
733                 window = NULL;
734                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
735                 
736                 /* Do not open again the message and present the
737                    window to the user */
738                 if (found) {
739                         if (window)
740                                 gtk_window_present (GTK_WINDOW (window));
741                         else
742                                 /* the header has been registered already, we don't do
743                                  * anything but wait for the window to come up*/
744                                 g_warning ("debug: header %p already registered, waiting for window",
745                                            header);
746                 } else {
747                         /* register the header before actually creating the window */
748                         modest_window_mgr_register_header (mgr, header);
749                                 
750                         if (!(flags & TNY_HEADER_FLAG_CACHED))
751                                 tny_list_append (not_opened_headers, G_OBJECT (header));
752                         /* Check if msg has already been retreived */
753                         else
754                                 tny_list_append (not_opened_cached_headers, G_OBJECT (header));
755                 }
756                 g_object_unref (header);
757                 tny_iterator_next (iter);
758         }
759         
760         /* Open each uncached message */
761         if (tny_list_get_length (not_opened_headers) > 0) {
762                 mail_op1 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
763                                                                          G_OBJECT (win), 
764                                                                          modest_ui_actions_get_msgs_full_error_handler, 
765                                                                          NULL);
766                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op1);
767                 if (tny_list_get_length (not_opened_headers) > 1) {
768                         modest_mail_operation_get_msgs_full (mail_op1, 
769                                                              not_opened_headers, 
770                                                              open_msg_cb, 
771                                                              NULL, 
772                                                              NULL);
773                 } else {
774                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
775                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
776                         modest_mail_operation_get_msg (mail_op1, header, open_msg_cb, NULL);
777                         g_object_unref (header);
778                         g_object_unref (iter);
779                 }
780         }
781
782         /* Open each cached message */
783         if (tny_list_get_length (not_opened_cached_headers) > 0) {
784                 mail_op2 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_OPEN, 
785                                                                          G_OBJECT (win), 
786                                                                          modest_ui_actions_get_msgs_full_error_handler, 
787                                                                          NULL);
788                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op2);
789                 if (tny_list_get_length (not_opened_cached_headers) > 1) {
790                         modest_mail_operation_get_msgs_full (mail_op2, 
791                                                              not_opened_headers, 
792                                                              open_msg_cb, 
793                                                              NULL, 
794                                                              NULL);
795                 } else {
796                         TnyIterator *iter = tny_list_create_iterator (not_opened_cached_headers);
797                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
798                         modest_mail_operation_get_msg (mail_op2, header, open_msg_cb, NULL);
799                         g_object_unref (header);
800                         g_object_unref (iter);
801                 }
802         }
803
804         /* Clean */
805         if (not_opened_headers != NULL)
806                 g_object_unref (not_opened_headers);
807         if (not_opened_cached_headers != NULL)
808                 g_object_unref (not_opened_cached_headers);
809         if (iter != NULL) 
810                 g_object_unref (iter);
811         if (mail_op1 != NULL)
812                 g_object_unref (mail_op1);
813         if (mail_op2 != NULL) 
814                 g_object_unref (mail_op2);
815 }
816
817 void
818 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
819 {
820         TnyList *headers;
821
822         /* Get headers */
823         headers = get_selected_headers (win);
824         if (!headers)
825                 return;
826
827         /* Open them */
828         _modest_ui_actions_open (headers, win);
829
830         g_object_unref(headers);
831 }
832
833
834 static void
835 free_reply_forward_helper (gpointer data)
836 {
837         ReplyForwardHelper *helper;
838
839         helper = (ReplyForwardHelper *) data;
840         g_free (helper->account_name);
841         g_slice_free (ReplyForwardHelper, helper);
842 }
843
844 static void
845 reply_forward_cb (ModestMailOperation *mail_op, 
846                   TnyHeader *header, 
847                   TnyMsg *msg,
848                   gpointer user_data)
849 {
850         TnyMsg *new_msg;
851         ReplyForwardHelper *rf_helper;
852         ModestWindow *msg_win = NULL;
853         ModestEditType edit_type;
854         gchar *from = NULL;
855         TnyAccount *account = NULL;
856         ModestWindowMgr *mgr = NULL;
857         gchar *signature = NULL;
858                         
859         g_return_if_fail (user_data != NULL);
860         rf_helper = (ReplyForwardHelper *) user_data;
861
862         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
863                                                    rf_helper->account_name);
864         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
865                                          rf_helper->account_name,
866                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
867                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
868                                                            rf_helper->account_name,
869                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
870         }
871
872         /* Create reply mail */
873         switch (rf_helper->action) {
874         case ACTION_REPLY:
875                 new_msg = 
876                         modest_tny_msg_create_reply_msg (msg,  from, signature,
877                                                          rf_helper->reply_forward_type,
878                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
879                 break;
880         case ACTION_REPLY_TO_ALL:
881                 new_msg = 
882                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
883                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
884                 edit_type = MODEST_EDIT_TYPE_REPLY;
885                 break;
886         case ACTION_FORWARD:
887                 new_msg = 
888                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
889                 edit_type = MODEST_EDIT_TYPE_FORWARD;
890                 break;
891         default:
892                 g_return_if_reached ();
893                 return;
894         }
895
896         g_free (signature);
897
898         if (!new_msg) {
899                 g_printerr ("modest: failed to create message\n");
900                 goto cleanup;
901         }
902
903         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
904                                                                        rf_helper->account_name,
905                                                                        TNY_ACCOUNT_TYPE_STORE);
906         if (!account) {
907                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
908                 goto cleanup;
909         }
910
911         /* Create and register the windows */
912         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
913         mgr = modest_runtime_get_window_mgr ();
914         modest_window_mgr_register_window (mgr, msg_win);
915
916         if (rf_helper->parent_window != NULL) {
917                 gdouble parent_zoom;
918
919                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
920                 modest_window_set_zoom (msg_win, parent_zoom);
921         }
922
923         /* Show edit window */
924         gtk_widget_show_all (GTK_WIDGET (msg_win));
925
926 cleanup:
927         if (msg_win)
928                 g_object_unref (msg_win);
929         if (new_msg)
930                 g_object_unref (G_OBJECT (new_msg));
931         if (account)
932                 g_object_unref (G_OBJECT (account));
933 /*      g_object_unref (msg); */
934         g_object_unref (header);
935 }
936
937 /*
938  * Checks a list of headers. If any of them are not currently
939  * downloaded (CACHED) then it asks the user for permission to
940  * download them.
941  *
942  * Returns FALSE if the user does not want to download the
943  * messages. Returns TRUE if the user allowed the download or if all
944  * of them are currently downloaded
945  */
946 static gboolean
947 download_uncached_messages (TnyList *header_list, GtkWindow *win)
948 {
949         TnyIterator *iter;
950         gboolean retval;
951         gint uncached_messages = 0;
952
953         iter = tny_list_create_iterator (header_list);
954         while (!tny_iterator_is_done (iter)) {
955                 TnyHeader *header;
956                 TnyHeaderFlags flags;
957
958                 header = TNY_HEADER (tny_iterator_get_current (iter));
959                 flags = tny_header_get_flags (header);
960                 /* TODO: is this the right flag?, it seems that some
961                    headers that have been previously downloaded do not
962                    come with it */
963                 if (! (flags & TNY_HEADER_FLAG_CACHED))
964                         uncached_messages ++;
965                 g_object_unref (header);
966                 tny_iterator_next (iter);
967         }
968         g_object_unref (iter);
969
970         /* Ask for user permission to download the messages */
971         retval = TRUE;
972         if (uncached_messages > 0) {
973                 GtkResponseType response;
974                 response = 
975                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
976                                                                  ngettext("mcen_nc_get_msg",
977                                                                           "mcen_nc_get_msgs",
978                                                                          uncached_messages));
979                 if (response == GTK_RESPONSE_CANCEL)
980                         retval = FALSE;
981         }
982         return retval;
983 }
984
985
986 /*
987  * Common code for the reply and forward actions
988  */
989 static void
990 reply_forward (ReplyForwardAction action, ModestWindow *win)
991 {
992         ModestMailOperation *mail_op = NULL;
993         TnyList *header_list = NULL;
994         ReplyForwardHelper *rf_helper = NULL;
995         guint reply_forward_type;
996         gboolean continue_download;
997         
998         g_return_if_fail (MODEST_IS_WINDOW(win));
999
1000         /* we need an account when editing */
1001         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1002                 run_account_setup_wizard (win);
1003                 return;
1004         }
1005         
1006         header_list = get_selected_headers (win);
1007         if (!header_list)
1008                 return;
1009
1010         /* Check that the messages have been previously downloaded */
1011         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
1012         if (!continue_download) {
1013                 g_object_unref (header_list);
1014                 return;
1015         }
1016         
1017         reply_forward_type = 
1018                 modest_conf_get_int (modest_runtime_get_conf (),
1019                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1020                                      NULL);
1021         /* We assume that we can only select messages of the
1022            same folder and that we reply all of them from the
1023            same account. In fact the interface currently only
1024            allows single selection */
1025         
1026         /* Fill helpers */
1027         rf_helper = g_slice_new0 (ReplyForwardHelper);
1028         rf_helper->reply_forward_type = reply_forward_type;
1029         rf_helper->action = action;
1030         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1031         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1032                 rf_helper->parent_window = GTK_WIDGET (win);
1033         if (!rf_helper->account_name)
1034                 rf_helper->account_name =
1035                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1036
1037         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1038                 TnyMsg *msg;
1039                 TnyHeader *header;
1040                 /* Get header and message. Do not free them here, the
1041                    reply_forward_cb must do it */
1042                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1043                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1044                 if (!msg || !header) {
1045                         if (msg)
1046                                 g_object_unref (msg);
1047                         if (header)
1048                                 g_object_unref (header);
1049                         g_printerr ("modest: no message found\n");
1050                         return;
1051                 } else
1052                         reply_forward_cb (NULL, header, msg, rf_helper);
1053         } else {
1054                 /* Retrieve messages */
1055                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1056                                                                          G_OBJECT(win),
1057                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1058                                                                          NULL);
1059                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1060                 modest_mail_operation_get_msgs_full (mail_op, 
1061                                                      header_list, 
1062                                                      reply_forward_cb, 
1063                                                      rf_helper, 
1064                                                      free_reply_forward_helper);
1065
1066                 /* Clean */
1067                 g_object_unref(mail_op);
1068         }
1069
1070         /* Free */
1071         g_object_unref (header_list);
1072 }
1073
1074 void
1075 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1076 {
1077         g_return_if_fail (MODEST_IS_WINDOW(win));
1078
1079         reply_forward (ACTION_REPLY, win);
1080 }
1081
1082 void
1083 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1084 {
1085         g_return_if_fail (MODEST_IS_WINDOW(win));
1086
1087         reply_forward (ACTION_FORWARD, win);
1088 }
1089
1090 void
1091 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1092 {
1093         g_return_if_fail (MODEST_IS_WINDOW(win));
1094
1095         reply_forward (ACTION_REPLY_TO_ALL, win);
1096 }
1097
1098 void 
1099 modest_ui_actions_on_next (GtkAction *action, 
1100                            ModestWindow *window)
1101 {
1102         if (MODEST_IS_MAIN_WINDOW (window)) {
1103                 GtkWidget *header_view;
1104
1105                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1106                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1107                 if (!header_view)
1108                         return;
1109         
1110                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1111         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1112                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1113         } else {
1114                 g_return_if_reached ();
1115         }
1116 }
1117
1118 void 
1119 modest_ui_actions_on_prev (GtkAction *action, 
1120                            ModestWindow *window)
1121 {
1122         g_return_if_fail (MODEST_IS_WINDOW(window));
1123
1124         if (MODEST_IS_MAIN_WINDOW (window)) {
1125                 GtkWidget *header_view;
1126                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1127                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1128                 if (!header_view)
1129                         return;
1130                 
1131                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1132         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1133                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1134         } else {
1135                 g_return_if_reached ();
1136         }
1137 }
1138
1139 void 
1140 modest_ui_actions_on_sort (GtkAction *action, 
1141                            ModestWindow *window)
1142 {
1143         g_return_if_fail (MODEST_IS_WINDOW(window));
1144
1145         if (MODEST_IS_MAIN_WINDOW (window)) {
1146                 GtkWidget *header_view;
1147                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1148                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1149                 if (!header_view)
1150                         return;
1151
1152                 /* Show sorting dialog */
1153                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1154         }
1155 }
1156
1157 static void
1158 new_messages_arrived (ModestMailOperation *self, 
1159                       gint new_messages,
1160                       gpointer user_data)
1161 {
1162         if (new_messages == 0)
1163                 return;
1164
1165         modest_platform_on_new_msg ();
1166 }
1167
1168 /*
1169  * This function performs the send & receive required actions. The
1170  * window is used to create the mail operation. Typically it should
1171  * always be the main window, but we pass it as argument in order to
1172  * be more flexible.
1173  */
1174 void
1175 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1176 {
1177         gchar *acc_name = NULL;
1178         ModestMailOperation *mail_op;
1179
1180         /* If no account name was provided then get the current account, and if
1181            there is no current account then pick the default one: */
1182         if (!account_name) {
1183                 acc_name = g_strdup (modest_window_get_active_account(win));
1184                 if (!acc_name)
1185                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1186                 if (!acc_name) {
1187                         g_printerr ("modest: cannot get default account\n");
1188                         return;
1189                 }
1190         } else {
1191                 acc_name = g_strdup (account_name);
1192         }
1193
1194         /* Set send/receive operation in progress */    
1195         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1196
1197 /*      mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win)); */
1198         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_OPEN,
1199                                                                  G_OBJECT (win),
1200                                                                  modest_ui_actions_send_receive_error_handler,
1201                                                                  NULL);
1202
1203         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1204                           G_CALLBACK (_on_send_receive_progress_changed), 
1205                           win);
1206
1207         /* Send & receive. */
1208         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1209         /* Receive and then send. The operation is tagged initially as
1210            a receive operation because the account update performs a
1211            receive and then a send. The operation changes its type
1212            internally, so the progress objects will receive the proper
1213            progress information */
1214         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1215         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1216         g_object_unref (G_OBJECT (mail_op));
1217         
1218         /* Free */
1219         g_free (acc_name);
1220 }
1221
1222 /*
1223  * Refreshes all accounts. This function will be used by automatic
1224  * updates
1225  */
1226 void
1227 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1228 {
1229         GSList *account_names, *iter;
1230
1231         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1232                                                           TRUE);
1233
1234         iter = account_names;
1235         while (iter) {                  
1236                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1237                 iter = g_slist_next (iter);
1238         }
1239
1240         modest_account_mgr_free_account_names (account_names);
1241         account_names = NULL;
1242 }
1243
1244 /*
1245  * Handler of the click on Send&Receive button in the main toolbar
1246  */
1247 void
1248 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1249 {
1250         /* Check if accounts exist */
1251         gboolean accounts_exist = 
1252                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1253         
1254         /* If not, allow the user to create an account before trying to send/receive. */
1255         if (!accounts_exist)
1256                 modest_ui_actions_on_accounts (NULL, win);
1257         
1258         /* Refresh the active account */
1259         modest_ui_actions_do_send_receive (NULL, win);
1260 }
1261
1262
1263 void
1264 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1265 {
1266         ModestConf *conf;
1267         GtkWidget *header_view;
1268         
1269         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1270
1271         header_view = modest_main_window_get_child_widget (main_window,
1272                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1273         if (!header_view)
1274                 return;
1275
1276         conf = modest_runtime_get_conf ();
1277         
1278         /* what is saved/restored is depending on the style; thus; we save with
1279          * old style, then update the style, and restore for this new style
1280          */
1281         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1282         
1283         if (modest_header_view_get_style
1284             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1285                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1286                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1287         else
1288                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1289                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1290
1291         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1292                                       MODEST_CONF_HEADER_VIEW_KEY);
1293 }
1294
1295
1296 void 
1297 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1298                                       TnyHeader *header,
1299                                       ModestMainWindow *main_window)
1300 {
1301         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1302         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1303         
1304         /* If no header has been selected then exit */
1305         if (!header)
1306                 return;
1307
1308         /* Update focus */
1309         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1310             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1311
1312         /* Update Main window title */
1313         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1314                 const gchar *subject = tny_header_get_subject (header);
1315                 if (subject && strlen(subject) > 0)
1316                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1317                 else
1318                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1319         }
1320
1321         /* Update toolbar dimming state */
1322         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1323 }
1324
1325 void
1326 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1327                                        TnyHeader *header,
1328                                        ModestMainWindow *main_window)
1329 {
1330         TnyList *headers;
1331
1332         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1333         
1334         if (!header)
1335                 return;
1336
1337         headers = tny_simple_list_new ();
1338         tny_list_prepend (headers, G_OBJECT (header));
1339
1340         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1341
1342         g_object_unref (headers);
1343 }
1344
1345 static void
1346 set_active_account_from_tny_account (TnyAccount *account,
1347                                      ModestWindow *window)
1348 {
1349         const gchar *server_acc_name = tny_account_get_id (account);
1350         
1351         /* We need the TnyAccount provided by the
1352            account store because that is the one that
1353            knows the name of the Modest account */
1354         TnyAccount *modest_server_account = modest_server_account = 
1355                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1356                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1357                                                              server_acc_name);
1358         
1359         const gchar *modest_acc_name = 
1360                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1361         modest_window_set_active_account (window, modest_acc_name);
1362         g_object_unref (modest_server_account);
1363 }
1364
1365
1366 static void
1367 folder_refreshed_cb (const GObject *obj, 
1368                      TnyFolder *folder, 
1369                      gpointer user_data)
1370 {
1371         ModestMainWindow *win = NULL;
1372         GtkWidget *header_view;
1373
1374         g_return_if_fail (TNY_IS_FOLDER (folder));
1375
1376         win = MODEST_MAIN_WINDOW (user_data);
1377         header_view = 
1378                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1379
1380         /* Check if folder is empty and set headers view contents style */
1381         if (tny_folder_get_all_count (folder) == 0) {
1382         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1383                 modest_main_window_set_contents_style (win,
1384                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1385         } else {
1386                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1387         }
1388 }
1389
1390 void 
1391 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1392                                                TnyFolderStore *folder_store, 
1393                                                gboolean selected,
1394                                                ModestMainWindow *main_window)
1395 {
1396         ModestConf *conf;
1397         GtkWidget *header_view;
1398
1399         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1400
1401         header_view = modest_main_window_get_child_widget(main_window,
1402                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1403         if (!header_view)
1404                 return;
1405         
1406         conf = modest_runtime_get_conf ();
1407
1408         if (TNY_IS_ACCOUNT (folder_store)) {
1409                 if (selected) {
1410                         /* Update active account */
1411                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1412                         /* Show account details */
1413                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1414                 }
1415         } else {
1416                 if (TNY_IS_FOLDER (folder_store) && selected) {
1417                         
1418                         /* Update the active account */
1419                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1420                         if (account) {
1421                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1422                                 g_object_unref (account);
1423                                 account = NULL;
1424                         }
1425
1426                         /* Set the header style by default, it could
1427                            be changed later by the refresh callback to
1428                            empty */
1429                         modest_main_window_set_contents_style (main_window, 
1430                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1431
1432                         /* Set folder on header view. This function
1433                            will call tny_folder_refresh_async so we
1434                            pass a callback that will be called when
1435                            finished. We use that callback to set the
1436                            empty view if there are no messages */
1437                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1438                                                        TNY_FOLDER (folder_store),
1439                                                        folder_refreshed_cb,
1440                                                        main_window);
1441                         
1442                         /* Restore configuration. We need to do this
1443                            *after* the set_folder because the widget
1444                            memory asks the header view about its
1445                            folder  */
1446                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1447                                                       G_OBJECT(header_view),
1448                                                       MODEST_CONF_HEADER_VIEW_KEY);
1449                 } else {
1450                         /* Update the active account */
1451                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1452                         /* Save only if we're seeing headers */
1453                         if (modest_main_window_get_contents_style (main_window) ==
1454                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1455                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1456                                                            MODEST_CONF_HEADER_VIEW_KEY);
1457                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1458                 }
1459         }
1460
1461         /* Update toolbar dimming state */
1462         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1463 }
1464
1465 void 
1466 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1467                                      ModestWindow *win)
1468 {
1469         GtkWidget *dialog;
1470         gchar *txt, *item;
1471         gboolean online;
1472
1473         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1474         
1475         online = tny_device_is_online (modest_runtime_get_device());
1476
1477         if (online) {
1478                 /* already online -- the item is simply not there... */
1479                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1480                                                  GTK_DIALOG_MODAL,
1481                                                  GTK_MESSAGE_WARNING,
1482                                                  GTK_BUTTONS_OK,
1483                                                  _("The %s you selected cannot be found"),
1484                                                  item);
1485                 gtk_dialog_run (GTK_DIALOG(dialog));
1486         } else {
1487                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1488                                                       GTK_WINDOW (win),
1489                                                       GTK_DIALOG_MODAL,
1490                                                       GTK_STOCK_CANCEL,
1491                                                       GTK_RESPONSE_REJECT,
1492                                                       GTK_STOCK_OK,
1493                                                       GTK_RESPONSE_ACCEPT,
1494                                                       NULL);
1495                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1496                                          "Do you want to get online?"), item);
1497                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1498                                     gtk_label_new (txt), FALSE, FALSE, 0);
1499                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1500                 g_free (txt);
1501
1502                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1503                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1504 //                      modest_platform_connect_and_wait ();
1505                 }
1506         }
1507         gtk_widget_destroy (dialog);
1508 }
1509
1510 void
1511 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1512                                      ModestWindow *win)
1513 {
1514         /* g_message ("%s %s", __FUNCTION__, link); */
1515 }       
1516
1517
1518 void
1519 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1520                                         ModestWindow *win)
1521 {
1522         modest_platform_activate_uri (link);
1523 }
1524
1525 void
1526 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1527                                           ModestWindow *win)
1528 {
1529         modest_platform_show_uri_popup (link);
1530 }
1531
1532 void
1533 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1534                                              ModestWindow *win)
1535 {
1536         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1537 }
1538
1539 void
1540 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1541                                           const gchar *address,
1542                                           ModestWindow *win)
1543 {
1544         /* g_message ("%s %s", __FUNCTION__, address); */
1545 }
1546
1547 void
1548 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1549 {
1550         TnyTransportAccount *transport_account;
1551         ModestMailOperation *mail_operation;
1552         MsgData *data;
1553         gchar *account_name, *from;
1554         ModestAccountMgr *account_mgr;
1555         gchar *info_text = NULL;
1556
1557         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1558         
1559         data = modest_msg_edit_window_get_msg_data (edit_window);
1560
1561         account_mgr = modest_runtime_get_account_mgr();
1562         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1563         if (!account_name) 
1564                 account_name = modest_account_mgr_get_default_account (account_mgr);
1565         if (!account_name) {
1566                 g_printerr ("modest: no account found\n");
1567                 modest_msg_edit_window_free_msg_data (edit_window, data);
1568                 return;
1569         }
1570
1571         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1572                 account_name = g_strdup (data->account_name);
1573         }
1574
1575         transport_account =
1576                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1577                                       (modest_runtime_get_account_store(),
1578                                        account_name,
1579                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1580         if (!transport_account) {
1581                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1582                 g_free (account_name);
1583                 modest_msg_edit_window_free_msg_data (edit_window, data);
1584                 return;
1585         }
1586         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1587
1588         /* Create the mail operation */         
1589         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1590         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1591
1592         modest_mail_operation_save_to_drafts (mail_operation,
1593                                               transport_account,
1594                                               data->draft_msg,
1595                                               from,
1596                                               data->to, 
1597                                               data->cc, 
1598                                               data->bcc,
1599                                               data->subject, 
1600                                               data->plain_body, 
1601                                               data->html_body,
1602                                               data->attachments,
1603                                               data->priority_flags);
1604         /* Frees */
1605         g_free (from);
1606         g_free (account_name);
1607         g_object_unref (G_OBJECT (transport_account));
1608         g_object_unref (G_OBJECT (mail_operation));
1609
1610         modest_msg_edit_window_free_msg_data (edit_window, data);
1611
1612         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1613         modest_platform_information_banner (NULL, NULL, info_text);
1614         g_free (info_text);
1615 }
1616
1617 /* For instance, when clicking the Send toolbar button when editing a message: */
1618 void
1619 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1620 {
1621         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1622
1623         if (!modest_msg_edit_window_check_names (edit_window))
1624                 return;
1625         
1626         /* FIXME: Code added just for testing. The final version will
1627            use the send queue provided by tinymail and some
1628            classifier */
1629         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1630         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1631         if (!account_name) 
1632                 account_name = modest_account_mgr_get_default_account (account_mgr);
1633                 
1634         if (!account_name) {
1635                 g_printerr ("modest: no account found\n");
1636                 return;
1637         }
1638         
1639         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1640
1641         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1642                 account_name = g_strdup (data->account_name);
1643         }
1644         
1645         /* Get the currently-active transport account for this modest account: */
1646         TnyTransportAccount *transport_account =
1647                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1648                                       (modest_runtime_get_account_store(),
1649                                        account_name));
1650         if (!transport_account) {
1651                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1652                 g_free (account_name);
1653                 modest_msg_edit_window_free_msg_data (edit_window, data);
1654                 return;
1655         }
1656         
1657         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1658
1659         /* mail content checks and dialogs */
1660         if (data->subject == NULL || data->subject[0] == '\0') {
1661                 GtkResponseType response;
1662                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1663                                                                     _("mcen_nc_subject_is_empty_send"));
1664                 if (response == GTK_RESPONSE_CANCEL) {
1665                         g_free (account_name);
1666                         return;
1667                 }
1668         }
1669
1670         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1671                 GtkResponseType response;
1672                 gchar *note_message;
1673                 gchar *note_subject = data->subject;
1674                 if (note_subject == NULL || note_subject[0] == '\0')
1675                         note_subject = _("mail_va_no_subject");
1676                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1677                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1678                                                                     note_message);
1679                 g_free (note_message);
1680                 if (response == GTK_RESPONSE_CANCEL) {
1681                         g_free (account_name);
1682                         return;
1683                 }
1684         }
1685
1686         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1687
1688         /* Create the mail operation */
1689         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1690         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1691
1692         modest_mail_operation_send_new_mail (mail_operation,
1693                                              transport_account,
1694                                              data->draft_msg,
1695                                              from,
1696                                              data->to, 
1697                                              data->cc, 
1698                                              data->bcc,
1699                                              data->subject, 
1700                                              data->plain_body, 
1701                                              data->html_body,
1702                                              data->attachments,
1703                                              data->priority_flags);
1704                                              
1705         /* Free data: */
1706         g_free (from);
1707         g_free (account_name);
1708         g_object_unref (G_OBJECT (transport_account));
1709         g_object_unref (G_OBJECT (mail_operation));
1710
1711         modest_msg_edit_window_free_msg_data (edit_window, data);
1712         modest_msg_edit_window_set_sent (edit_window, TRUE);
1713
1714         /* Save settings and close the window: */
1715         gtk_widget_destroy (GTK_WIDGET (edit_window));
1716 }
1717
1718 void 
1719 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1720                                   ModestMsgEditWindow *window)
1721 {
1722         ModestMsgEditFormatState *format_state = NULL;
1723
1724         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1725         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1726
1727         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1728                 return;
1729
1730         format_state = modest_msg_edit_window_get_format_state (window);
1731         g_return_if_fail (format_state != NULL);
1732
1733         format_state->bold = gtk_toggle_action_get_active (action);
1734         modest_msg_edit_window_set_format_state (window, format_state);
1735         g_free (format_state);
1736         
1737 }
1738
1739 void 
1740 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1741                                      ModestMsgEditWindow *window)
1742 {
1743         ModestMsgEditFormatState *format_state = NULL;
1744
1745         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1746         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1747
1748         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1749                 return;
1750
1751         format_state = modest_msg_edit_window_get_format_state (window);
1752         g_return_if_fail (format_state != NULL);
1753
1754         format_state->italics = gtk_toggle_action_get_active (action);
1755         modest_msg_edit_window_set_format_state (window, format_state);
1756         g_free (format_state);
1757         
1758 }
1759
1760 void 
1761 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1762                                      ModestMsgEditWindow *window)
1763 {
1764         ModestMsgEditFormatState *format_state = NULL;
1765
1766         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1767         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1768
1769         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1770                 return;
1771
1772         format_state = modest_msg_edit_window_get_format_state (window);
1773         g_return_if_fail (format_state != NULL);
1774
1775         format_state->bullet = gtk_toggle_action_get_active (action);
1776         modest_msg_edit_window_set_format_state (window, format_state);
1777         g_free (format_state);
1778         
1779 }
1780
1781 void 
1782 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1783                                      GtkRadioAction *selected,
1784                                      ModestMsgEditWindow *window)
1785 {
1786         ModestMsgEditFormatState *format_state = NULL;
1787         GtkJustification value;
1788
1789         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1790
1791         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1792                 return;
1793
1794         value = gtk_radio_action_get_current_value (selected);
1795
1796         format_state = modest_msg_edit_window_get_format_state (window);
1797         g_return_if_fail (format_state != NULL);
1798
1799         format_state->justification = value;
1800         modest_msg_edit_window_set_format_state (window, format_state);
1801         g_free (format_state);
1802 }
1803
1804 void 
1805 modest_ui_actions_on_select_editor_color (GtkAction *action,
1806                                           ModestMsgEditWindow *window)
1807 {
1808         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1809         g_return_if_fail (GTK_IS_ACTION (action));
1810
1811         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1812                 return;
1813
1814         modest_msg_edit_window_select_color (window);
1815 }
1816
1817 void 
1818 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1819                                                      ModestMsgEditWindow *window)
1820 {
1821         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1822         g_return_if_fail (GTK_IS_ACTION (action));
1823
1824         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1825                 return;
1826
1827         modest_msg_edit_window_select_background_color (window);
1828 }
1829
1830 void 
1831 modest_ui_actions_on_insert_image (GtkAction *action,
1832                                    ModestMsgEditWindow *window)
1833 {
1834         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1835         g_return_if_fail (GTK_IS_ACTION (action));
1836
1837         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1838                 return;
1839
1840         modest_msg_edit_window_insert_image (window);
1841 }
1842
1843 void 
1844 modest_ui_actions_on_attach_file (GtkAction *action,
1845                                   ModestMsgEditWindow *window)
1846 {
1847         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1848         g_return_if_fail (GTK_IS_ACTION (action));
1849
1850         modest_msg_edit_window_attach_file (window);
1851 }
1852
1853 void 
1854 modest_ui_actions_on_remove_attachments (GtkAction *action,
1855                                          ModestMsgEditWindow *window)
1856 {
1857         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1858         g_return_if_fail (GTK_IS_ACTION (action));
1859
1860         modest_msg_edit_window_remove_attachments (window, NULL);
1861 }
1862
1863 void 
1864 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1865 {
1866         TnyFolderStore *parent_folder;
1867         GtkWidget *folder_view;
1868         
1869         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1870
1871         folder_view = modest_main_window_get_child_widget (main_window,
1872                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1873         if (!folder_view)
1874                 return;
1875
1876         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1877         
1878         if (parent_folder) {
1879                 gboolean finished = FALSE;
1880                 gint result;
1881                 gchar *folder_name = NULL, *suggested_name = NULL;
1882
1883                 /* Run the new folder dialog */
1884                 while (!finished) {
1885                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1886                                                                         parent_folder,
1887                                                                         suggested_name,
1888                                                                         &folder_name);
1889
1890                         if (result == GTK_RESPONSE_REJECT) {
1891                                 finished = TRUE;
1892                         } else {
1893                                 ModestMailOperation *mail_op;
1894                                 TnyFolder *new_folder = NULL;
1895
1896                                 mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
1897                                                                       G_OBJECT(main_window));
1898                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1899                                                                  mail_op);
1900                                 new_folder = modest_mail_operation_create_folder (mail_op,
1901                                                                                   parent_folder,
1902                                                                                   (const gchar *) folder_name);
1903                                 if (new_folder) {
1904                                         g_object_unref (new_folder);
1905                                         finished = TRUE;
1906                                 }
1907                                 g_object_unref (mail_op);
1908                         }
1909                         g_free (folder_name);
1910                         folder_name = NULL;
1911                 }
1912
1913                 g_object_unref (parent_folder);
1914         }
1915 }
1916
1917 static void
1918 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
1919                                                gpointer user_data)
1920 {
1921         GObject *win = modest_mail_operation_get_source (mail_op);
1922
1923         /* TODO: what should we do in case of this error ? */
1924         g_warning ("Invalid folder name");
1925
1926         g_object_unref (win);
1927 }
1928
1929 void 
1930 modest_ui_actions_on_rename_folder (GtkAction *action,
1931                                      ModestMainWindow *main_window)
1932 {
1933         TnyFolderStore *folder;
1934         GtkWidget *folder_view;
1935         GtkWidget *header_view; 
1936
1937         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1938
1939         folder_view = modest_main_window_get_child_widget (main_window,
1940                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1941         if (!folder_view)
1942                 return;
1943
1944         header_view = modest_main_window_get_child_widget (main_window,
1945                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1946         
1947         if (!header_view)
1948                 return;
1949
1950         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1951         
1952         if (folder && TNY_IS_FOLDER (folder)) {
1953                 gchar *folder_name;
1954                 gint response;
1955                 const gchar *current_name;
1956
1957                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
1958                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
1959                                                                      current_name, &folder_name);
1960
1961                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
1962                         ModestMailOperation *mail_op;
1963
1964                         mail_op = 
1965                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
1966                                                                                G_OBJECT(main_window),
1967                                                                                modest_ui_actions_rename_folder_error_handler,
1968                                                                                NULL);
1969
1970
1971                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1972                                                          mail_op);
1973
1974                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
1975
1976                         modest_mail_operation_rename_folder (mail_op,
1977                                                              TNY_FOLDER (folder),
1978                                                              (const gchar *) folder_name);
1979
1980                         g_object_unref (mail_op);
1981                         g_free (folder_name);
1982                 }
1983                 g_object_unref (folder);
1984         }
1985 }
1986
1987 static void
1988 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1989                                                gpointer user_data)
1990 {
1991         GObject *win = modest_mail_operation_get_source (mail_op);
1992
1993         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1994                                                 _("mail_in_ui_folder_delete_error"));
1995         g_object_unref (win);
1996 }
1997
1998 static void
1999 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2000 {
2001         TnyFolderStore *folder;
2002         GtkWidget *folder_view;
2003         gint response;
2004         gchar *message;
2005         
2006         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2007
2008         folder_view = modest_main_window_get_child_widget (main_window,
2009                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2010         if (!folder_view)
2011                 return;
2012
2013         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2014
2015         /* Show an error if it's an account */
2016         if (!TNY_IS_FOLDER (folder)) {
2017                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2018                                                         _("mail_in_ui_folder_delete_error"));
2019                 return ;
2020         }
2021
2022         /* Ask the user */      
2023         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2024                                     tny_folder_get_name (TNY_FOLDER (folder)));
2025         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2026                                                             (const gchar *) message);
2027         g_free (message);
2028
2029         if (response == GTK_RESPONSE_OK) {
2030                 ModestMailOperation *mail_op = 
2031                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2032                                                                        G_OBJECT(main_window),
2033                                                                        modest_ui_actions_delete_folder_error_handler,
2034                                                                        NULL);
2035
2036                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2037                                                  mail_op);
2038                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2039                 g_object_unref (G_OBJECT (mail_op));
2040         }
2041
2042         g_object_unref (G_OBJECT (folder));
2043 }
2044
2045 void 
2046 modest_ui_actions_on_delete_folder (GtkAction *action,
2047                                      ModestMainWindow *main_window)
2048 {
2049         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2050
2051         delete_folder (main_window, FALSE);
2052 }
2053
2054 void 
2055 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2056 {
2057         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2058         
2059         delete_folder (main_window, TRUE);
2060 }
2061
2062 void
2063 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2064                                          const gchar* server_account_name,
2065                                          gchar **username,
2066                                          gchar **password, 
2067                                          gboolean *cancel, 
2068                                          gboolean *remember,
2069                                          ModestMainWindow *main_window)
2070 {
2071         g_return_if_fail(server_account_name);
2072         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2073         
2074         /* Initalize output parameters: */
2075         if (cancel)
2076                 *cancel = FALSE;
2077                 
2078         if (remember)
2079                 *remember = TRUE;
2080                 
2081 #ifdef MODEST_PLATFORM_MAEMO
2082         /* Maemo uses a different (awkward) button order,
2083          * It should probably just use gtk_alternative_dialog_button_order ().
2084          */
2085         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2086                                               NULL,
2087                                               GTK_DIALOG_MODAL,
2088                                               GTK_STOCK_OK,
2089                                               GTK_RESPONSE_ACCEPT,
2090                                               GTK_STOCK_CANCEL,
2091                                               GTK_RESPONSE_REJECT,
2092                                               NULL);
2093 #else
2094         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2095                                               NULL,
2096                                               GTK_DIALOG_MODAL,
2097                                               GTK_STOCK_CANCEL,
2098                                               GTK_RESPONSE_REJECT,
2099                                               GTK_STOCK_OK,
2100                                               GTK_RESPONSE_ACCEPT,
2101                                               NULL);
2102 #endif /* MODEST_PLATFORM_MAEMO */
2103
2104         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2105         
2106         gchar *server_name = modest_server_account_get_hostname (
2107                 modest_runtime_get_account_mgr(), server_account_name);
2108         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2109                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2110                 *cancel = TRUE;
2111                 return;
2112         }
2113         
2114         /* This causes a warning because the logical ID has no %s in it, 
2115          * though the translation does, but there is not much we can do about that: */
2116         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2117         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2118                             FALSE, FALSE, 0);
2119         g_free (txt);
2120         g_free (server_name);
2121         server_name = NULL;
2122
2123         /* username: */
2124         gchar *initial_username = modest_server_account_get_username (
2125                 modest_runtime_get_account_mgr(), server_account_name);
2126         
2127         GtkWidget *entry_username = gtk_entry_new ();
2128         if (initial_username)
2129                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2130         /* Dim this if a connection has ever succeeded with this username,
2131          * as per the UI spec: */
2132         const gboolean username_known = 
2133                 modest_server_account_get_username_has_succeeded(
2134                         modest_runtime_get_account_mgr(), server_account_name);
2135         gtk_widget_set_sensitive (entry_username, !username_known);
2136         
2137 #ifdef MODEST_PLATFORM_MAEMO
2138         /* Auto-capitalization is the default, so let's turn it off: */
2139         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2140         
2141         /* Create a size group to be used by all captions.
2142          * Note that HildonCaption does not create a default size group if we do not specify one.
2143          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2144         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2145         
2146         GtkWidget *caption = hildon_caption_new (sizegroup, 
2147                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2148         gtk_widget_show (entry_username);
2149         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2150                 FALSE, FALSE, MODEST_MARGIN_HALF);
2151         gtk_widget_show (caption);
2152 #else 
2153         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2154                             TRUE, FALSE, 0);
2155 #endif /* MODEST_PLATFORM_MAEMO */      
2156                             
2157         /* password: */
2158         GtkWidget *entry_password = gtk_entry_new ();
2159         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2160         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2161         
2162 #ifdef MODEST_PLATFORM_MAEMO
2163         /* Auto-capitalization is the default, so let's turn it off: */
2164         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2165                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2166         
2167         caption = hildon_caption_new (sizegroup, 
2168                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2169         gtk_widget_show (entry_password);
2170         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2171                 FALSE, FALSE, MODEST_MARGIN_HALF);
2172         gtk_widget_show (caption);
2173         g_object_unref (sizegroup);
2174 #else 
2175         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2176                             TRUE, FALSE, 0);
2177 #endif /* MODEST_PLATFORM_MAEMO */      
2178                                 
2179 /* This is not in the Maemo UI spec:
2180         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2181         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2182                             TRUE, FALSE, 0);
2183 */
2184
2185         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2186         
2187         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2188                 if (username) {
2189                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2190                         
2191                         modest_server_account_set_username (
2192                                  modest_runtime_get_account_mgr(), server_account_name, 
2193                                  *username);
2194                                  
2195                         const gboolean username_was_changed = 
2196                                 (strcmp (*username, initial_username) != 0);
2197                         if (username_was_changed) {
2198                                 g_warning ("%s: tinymail does not yet support changing the "
2199                                         "username in the get_password() callback.\n", __FUNCTION__);
2200                         }
2201                 }
2202                         
2203                 if (password) {
2204                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2205                         
2206                         /* We do not save the password in the configuration, 
2207                          * because this function is only called for passwords that should 
2208                          * not be remembered:
2209                         modest_server_account_set_password (
2210                                  modest_runtime_get_account_mgr(), server_account_name, 
2211                                  *password);
2212                         */
2213                 }
2214                 
2215                 if (cancel)
2216                         *cancel   = FALSE;
2217                         
2218         } else {
2219                 if (username)
2220                         *username = NULL;
2221                         
2222                 if (password)
2223                         *password = NULL;
2224                         
2225                 if (cancel)
2226                         *cancel   = TRUE;
2227         }
2228
2229 /* This is not in the Maemo UI spec:
2230         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2231                 *remember = TRUE;
2232         else
2233                 *remember = FALSE;
2234 */
2235
2236         gtk_widget_destroy (dialog);
2237         
2238         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2239 }
2240
2241 void
2242 modest_ui_actions_on_cut (GtkAction *action,
2243                           ModestWindow *window)
2244 {
2245         GtkWidget *focused_widget;
2246
2247         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2248         if (GTK_IS_EDITABLE (focused_widget)) {
2249                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2250         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2251                 GtkTextBuffer *buffer;
2252                 GtkClipboard *clipboard;
2253
2254                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2255                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2256                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2257         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2258                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2259         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2260                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2261         }
2262 }
2263
2264 void
2265 modest_ui_actions_on_copy (GtkAction *action,
2266                            ModestWindow *window)
2267 {
2268         GtkClipboard *clipboard;
2269         GtkWidget *focused_widget;
2270
2271         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2272         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2273
2274         if (GTK_IS_LABEL (focused_widget)) {
2275                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2276         } else if (GTK_IS_EDITABLE (focused_widget)) {
2277                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2278         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2279                 GtkTextBuffer *buffer;
2280                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2281                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2282                 modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2283         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2284                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2285                 TnyIterator *iter = tny_list_create_iterator (header_list);
2286                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2287                 TnyFolder *folder = tny_header_get_folder (header);
2288                 TnyAccount *account = tny_folder_get_account (folder);
2289                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2290                 /* If it's POP then ask */
2291                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2292                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2293                 g_object_unref (account);
2294                 g_object_unref (folder);
2295                 g_object_unref (header);
2296                 g_object_unref (iter);
2297                 
2298                 /* Check that the messages have been previously downloaded */
2299                 gboolean continue_download = TRUE;
2300                 if (ask)
2301                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2302                 if (continue_download)
2303                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2304                 g_object_unref (header_list);
2305         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2306                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2307         }    
2308
2309         /* Show information banner */
2310         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2311         
2312 }
2313
2314 void
2315 modest_ui_actions_on_undo (GtkAction *action,
2316                            ModestWindow *window)
2317 {
2318         ModestEmailClipboard *clipboard = NULL;
2319
2320         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2321                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2322         } if (MODEST_IS_MAIN_WINDOW (window)) {
2323                 /* Clear clipboard source */
2324                 clipboard = modest_runtime_get_email_clipboard ();
2325                 modest_email_clipboard_clear (clipboard);               
2326         }
2327         else {
2328                 g_return_if_reached ();
2329         }
2330 }
2331
2332 void
2333 modest_ui_actions_on_paste (GtkAction *action,
2334                             ModestWindow *window)
2335 {
2336         GtkWidget *focused_widget;
2337         ModestMailOperation *mail_op = NULL;
2338
2339         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2340         if (GTK_IS_EDITABLE (focused_widget)) {
2341                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2342         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2343                 GtkTextBuffer *buffer;
2344                 GtkClipboard *clipboard;
2345
2346                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2347                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2348                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2349         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2350                 ModestEmailClipboard *clipboard = NULL;
2351                 TnyFolder *src_folder = NULL;
2352                 TnyFolderStore *folder_store = NULL;
2353                 TnyList *data = NULL;           
2354                 gboolean delete = FALSE;
2355                 
2356                 /* Check clipboard source */
2357                 clipboard = modest_runtime_get_email_clipboard ();
2358                 if (modest_email_clipboard_cleared (clipboard)) 
2359                         return;
2360                 
2361                 /* Get elements to paste */
2362                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2363
2364                 /* Create a new mail operation */
2365                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2366                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2367                                                  mail_op);
2368                 
2369                 /* Get destination folder */
2370                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2371
2372                 /* transfer messages  */
2373                 if (data != NULL) {
2374                         modest_mail_operation_xfer_msgs (mail_op, 
2375                                                          data,
2376                                                          TNY_FOLDER (folder_store),
2377                                                          delete,
2378                                                          NULL,
2379                                                          NULL);
2380                         
2381                 } else if (src_folder != NULL) {                        
2382                         modest_mail_operation_xfer_folder (mail_op, 
2383                                                            src_folder,
2384                                                            folder_store,
2385                                                            delete);
2386                 }
2387
2388                 /* Free */
2389                 if (data != NULL) 
2390                         g_object_unref (data);
2391                 if (src_folder != NULL) 
2392                         g_object_unref (src_folder);
2393                 if (folder_store != NULL) 
2394                         g_object_unref (folder_store);
2395         }
2396 }
2397
2398 void
2399 modest_ui_actions_on_select_all (GtkAction *action,
2400                                  ModestWindow *window)
2401 {
2402         GtkWidget *focused_widget;
2403
2404         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2405         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2406                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2407         } else if (GTK_IS_LABEL (focused_widget)) {
2408                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2409         } else if (GTK_IS_EDITABLE (focused_widget)) {
2410                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2411         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2412                 GtkTextBuffer *buffer;
2413                 GtkTextIter start, end;
2414
2415                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2416                 gtk_text_buffer_get_start_iter (buffer, &start);
2417                 gtk_text_buffer_get_end_iter (buffer, &end);
2418                 gtk_text_buffer_select_range (buffer, &start, &end);
2419         } else if (GTK_IS_HTML (focused_widget)) {
2420                 gtk_html_select_all (GTK_HTML (focused_widget));
2421         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2422                 GtkWidget *header_view = focused_widget;
2423                 GtkTreeSelection *selection = NULL;
2424                 
2425                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2426                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2427                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2428                                 
2429                 /* Select all messages */
2430                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2431                 gtk_tree_selection_select_all (selection);
2432
2433                 /* Set focuse on header view */
2434                 gtk_widget_grab_focus (header_view);
2435         }
2436
2437 }
2438
2439 void
2440 modest_ui_actions_on_mark_as_read (GtkAction *action,
2441                                    ModestWindow *window)
2442 {       
2443         g_return_if_fail (MODEST_IS_WINDOW(window));
2444                 
2445         /* Mark each header as read */
2446         do_headers_action (window, headers_action_mark_as_read, NULL);
2447 }
2448
2449 void
2450 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2451                                      ModestWindow *window)
2452 {       
2453         g_return_if_fail (MODEST_IS_WINDOW(window));
2454                 
2455         /* Mark each header as read */
2456         do_headers_action (window, headers_action_mark_as_unread, NULL);
2457 }
2458
2459 void
2460 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2461                                   GtkRadioAction *selected,
2462                                   ModestWindow *window)
2463 {
2464         gint value;
2465
2466         value = gtk_radio_action_get_current_value (selected);
2467         if (MODEST_IS_WINDOW (window)) {
2468                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2469         }
2470 }
2471
2472 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2473                                                         GtkRadioAction *selected,
2474                                                         ModestWindow *window)
2475 {
2476         TnyHeaderFlags flags;
2477         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2478
2479         flags = gtk_radio_action_get_current_value (selected);
2480         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2481 }
2482
2483 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2484                                                            GtkRadioAction *selected,
2485                                                            ModestWindow *window)
2486 {
2487         gint file_format;
2488
2489         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2490
2491         file_format = gtk_radio_action_get_current_value (selected);
2492         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2493 }
2494
2495
2496 void     
2497 modest_ui_actions_on_zoom_plus (GtkAction *action,
2498                                 ModestWindow *window)
2499 {
2500         g_return_if_fail (MODEST_IS_WINDOW (window));
2501
2502         modest_window_zoom_plus (MODEST_WINDOW (window));
2503 }
2504
2505 void     
2506 modest_ui_actions_on_zoom_minus (GtkAction *action,
2507                                  ModestWindow *window)
2508 {
2509         g_return_if_fail (MODEST_IS_WINDOW (window));
2510
2511         modest_window_zoom_minus (MODEST_WINDOW (window));
2512 }
2513
2514 void     
2515 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2516                                            ModestWindow *window)
2517 {
2518         ModestWindowMgr *mgr;
2519         gboolean fullscreen, active;
2520         g_return_if_fail (MODEST_IS_WINDOW (window));
2521
2522         mgr = modest_runtime_get_window_mgr ();
2523
2524         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2525         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2526
2527         if (active != fullscreen) {
2528                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2529                 gtk_window_present (GTK_WINDOW (window));
2530         }
2531 }
2532
2533 void
2534 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2535                                         ModestWindow *window)
2536 {
2537         ModestWindowMgr *mgr;
2538         gboolean fullscreen;
2539
2540         g_return_if_fail (MODEST_IS_WINDOW (window));
2541
2542         mgr = modest_runtime_get_window_mgr ();
2543         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2544         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2545
2546         gtk_window_present (GTK_WINDOW (window));
2547 }
2548
2549 /* 
2550  * Used by modest_ui_actions_on_details to call do_headers_action 
2551  */
2552 static void
2553 headers_action_show_details (TnyHeader *header, 
2554                              ModestWindow *window,
2555                              gpointer user_data)
2556
2557 {
2558         GtkWidget *dialog;
2559         
2560         /* Create dialog */
2561         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2562
2563         /* Run dialog */
2564         gtk_widget_show_all (dialog);
2565         gtk_dialog_run (GTK_DIALOG (dialog));
2566
2567         gtk_widget_destroy (dialog);
2568 }
2569
2570 /*
2571  * Show the folder details in a ModestDetailsDialog widget
2572  */
2573 static void
2574 show_folder_details (TnyFolder *folder, 
2575                      GtkWindow *window)
2576 {
2577         GtkWidget *dialog;
2578         
2579         /* Create dialog */
2580         dialog = modest_details_dialog_new_with_folder (window, folder);
2581
2582         /* Run dialog */
2583         gtk_widget_show_all (dialog);
2584         gtk_dialog_run (GTK_DIALOG (dialog));
2585
2586         gtk_widget_destroy (dialog);
2587 }
2588
2589 /*
2590  * Show the header details in a ModestDetailsDialog widget
2591  */
2592 void     
2593 modest_ui_actions_on_details (GtkAction *action, 
2594                               ModestWindow *win)
2595 {
2596         TnyList * headers_list;
2597         TnyIterator *iter;
2598         TnyHeader *header;              
2599
2600         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2601                 TnyMsg *msg;
2602
2603                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2604                 if (!msg)
2605                         return;
2606                 g_object_unref (msg);           
2607
2608                 headers_list = get_selected_headers (win);
2609                 if (!headers_list)
2610                         return;
2611
2612                 iter = tny_list_create_iterator (headers_list);
2613
2614                 header = TNY_HEADER (tny_iterator_get_current (iter));
2615                 headers_action_show_details (header, win, NULL);
2616                 g_object_unref (header);
2617
2618                 g_object_unref (iter);
2619                 g_object_unref (headers_list);
2620
2621         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2622                 GtkWidget *folder_view, *header_view;
2623
2624                 /* Check which widget has the focus */
2625                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2626                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2627                 if (gtk_widget_is_focus (folder_view)) {
2628                         TnyFolderStore *folder_store
2629                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2630                         if (!folder_store) {
2631                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
2632                                 return; 
2633                         }
2634                         /* Show only when it's a folder */
2635                         /* This function should not be called for account items, 
2636                          * because we dim the menu item for them. */
2637                         if (TNY_IS_FOLDER (folder_store)) {
2638                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
2639                         }
2640
2641                         g_object_unref (folder_store);
2642
2643                 } else {
2644                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2645                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2646                         /* Show details of each header */
2647                         do_headers_action (win, headers_action_show_details, header_view);
2648                 }
2649         }
2650 }
2651
2652 void     
2653 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2654                                      ModestMsgEditWindow *window)
2655 {
2656         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2657
2658         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2659 }
2660
2661 void     
2662 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2663                                       ModestMsgEditWindow *window)
2664 {
2665         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2666
2667         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2668 }
2669
2670 void
2671 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2672                                        ModestMainWindow *main_window)
2673 {
2674         ModestConf *conf;
2675         
2676         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2677
2678         conf = modest_runtime_get_conf ();
2679         
2680         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2681                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2682         else
2683                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2684 }
2685
2686 void 
2687 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2688                                      ModestWindow *window)
2689 {
2690         gboolean active, fullscreen = FALSE;
2691         ModestWindowMgr *mgr;
2692
2693         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2694
2695         /* Check if we want to toggle the toolbar vuew in fullscreen
2696            or normal mode */
2697         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2698                      "ViewShowToolbarFullScreen")) {
2699                 fullscreen = TRUE;
2700         }
2701
2702         /* Toggle toolbar */
2703         mgr = modest_runtime_get_window_mgr ();
2704         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2705 }
2706
2707 void     
2708 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2709                                            ModestMsgEditWindow *window)
2710 {
2711         modest_msg_edit_window_select_font (window);
2712 }
2713
2714 void
2715 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2716                                                   const gchar *display_name,
2717                                                   GtkWindow *window)
2718 {
2719         /* Do not change the application name if the widget has not
2720            the focus. This callback could be called even if the folder
2721            view has not the focus, because the handled signal could be
2722            emitted when the folder view is redrawn */
2723         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2724                 if (display_name)
2725                         gtk_window_set_title (window, display_name);
2726                 else
2727                         gtk_window_set_title (window, " ");
2728         }
2729 }
2730
2731 void
2732 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2733 {
2734         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2735         modest_msg_edit_window_select_contacts (window);
2736 }
2737
2738 void
2739 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2740 {
2741         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2742         modest_msg_edit_window_check_names (window);
2743 }
2744
2745
2746 static GtkWidget*
2747 create_move_to_dialog (ModestWindow *win,
2748                        GtkWidget *folder_view,
2749                        GtkWidget **tree_view)
2750 {
2751         GtkWidget *dialog, *scroll;
2752
2753         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2754                                               GTK_WINDOW (win),
2755                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2756                                               GTK_STOCK_OK,
2757                                               GTK_RESPONSE_ACCEPT,
2758                                               GTK_STOCK_CANCEL,
2759                                               GTK_RESPONSE_REJECT,
2760                                               NULL);
2761
2762         /* Create scrolled window */
2763         scroll = gtk_scrolled_window_new (NULL, NULL);
2764         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2765                                          GTK_POLICY_AUTOMATIC,
2766                                          GTK_POLICY_AUTOMATIC);
2767
2768         /* Create folder view */
2769         *tree_view = modest_platform_create_folder_view (NULL);
2770
2771         /* It could happen that we're trying to move a message from a
2772            window (msg window for example) after the main window was
2773            closed, so we can not just get the model of the folder
2774            view */
2775         if (MODEST_IS_FOLDER_VIEW (folder_view))
2776                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2777                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2778         else
2779                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
2780                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
2781
2782         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2783
2784         /* Add scroll to dialog */
2785         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2786                             scroll, FALSE, FALSE, 0);
2787
2788         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2789
2790         /* Select INBOX or local account */
2791         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
2792
2793         return dialog;
2794 }
2795
2796 /*
2797  * Returns TRUE if at least one of the headers of the list belongs to
2798  * a message that has been fully retrieved.
2799  */
2800 static gboolean
2801 has_retrieved_msgs (TnyList *list)
2802 {
2803         TnyIterator *iter;
2804         gboolean found = FALSE;
2805
2806         iter = tny_list_create_iterator (list);
2807         while (tny_iterator_is_done (iter) && !found) {
2808                 TnyHeader *header;
2809                 TnyHeaderFlags flags;
2810
2811                 header = TNY_HEADER (tny_iterator_get_current (iter));
2812                 flags = tny_header_get_flags (header);
2813                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2814                         found = TRUE;
2815
2816                 if (!found)
2817                         tny_iterator_next (iter);
2818         }
2819         g_object_unref (iter);
2820
2821         return found;
2822 }
2823
2824 /*
2825  * Shows a confirmation dialog to the user when we're moving messages
2826  * from a remote server to the local storage. Returns the dialog
2827  * response. If it's other kind of movement the it always returns
2828  * GTK_RESPONSE_OK
2829  */
2830 static gint
2831 msgs_move_to_confirmation (GtkWindow *win,
2832                            TnyFolder *dest_folder,
2833                            TnyList *headers)
2834 {
2835         gint response = GTK_RESPONSE_OK;
2836
2837         /* If the destination is a local folder */
2838         if (modest_tny_folder_is_local_folder (dest_folder)) {
2839                 TnyFolder *src_folder;
2840                 TnyIterator *iter;
2841                 TnyHeader *header;
2842
2843                 /* Get source folder */
2844                 iter = tny_list_create_iterator (headers);
2845                 header = TNY_HEADER (tny_iterator_get_current (iter));
2846                 src_folder = tny_header_get_folder (header);
2847                 g_object_unref (header);
2848                 g_object_unref (iter);
2849
2850                 /* if no src_folder, message may be an attahcment */
2851                 if (src_folder == NULL) 
2852                         return GTK_RESPONSE_CANCEL;
2853
2854                 /* If the source is a remote folder */
2855                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2856                         const gchar *message;
2857                         
2858                         if (has_retrieved_msgs (headers))
2859                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
2860                                                     tny_list_get_length (headers));
2861                         else 
2862                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
2863                                                     tny_list_get_length (headers));
2864
2865                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2866                                                                             (const gchar *) message);
2867                 }
2868                 g_object_unref (src_folder);
2869         }
2870         return response;
2871 }
2872
2873
2874 static void
2875 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2876 {
2877         ModestMsgViewWindow *self = NULL;
2878         gboolean last, first;
2879
2880         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2881         self = MODEST_MSG_VIEW_WINDOW (object);
2882         
2883         last = modest_msg_view_window_last_message_selected (self);
2884         first = modest_msg_view_window_first_message_selected (self);   
2885         if (last & first) {
2886                 /* No more messages to view, so close this window */
2887 /*              gboolean ret_value; */
2888 /*              g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
2889                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
2890         } else if (last)
2891                 modest_msg_view_window_select_previous_message (self);
2892         else 
2893                 modest_msg_view_window_select_next_message (self);
2894 }
2895
2896 void
2897 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
2898                                              gpointer user_data)
2899 {
2900         GObject *win = modest_mail_operation_get_source (mail_op);
2901
2902         /* TODO: show error message */
2903         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2904                                                 _("mail_in_ui_folder_move_target_error"));
2905         g_object_unref (win);
2906 }
2907
2908 void
2909 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
2910                                               gpointer user_data)
2911 {
2912         GObject *win = modest_mail_operation_get_source (mail_op);
2913         const GError *error = modest_mail_operation_get_error (mail_op);
2914
2915         g_return_if_fail (error != NULL);
2916         if (error->message != NULL)             
2917                 g_printerr ("modest: %s\n", error->message);
2918         else
2919                 g_printerr ("modest: unkonw error on sedn&receive operation");
2920
2921         /* Show error message */
2922         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2923                                                 _CS("sfil_ib_unable_to_send")); 
2924 /*      g_object_unref (win); */
2925 }
2926
2927 static void
2928 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
2929                        TnyHeader *header, 
2930                        TnyMsg *msg, 
2931                        gpointer user_data)
2932 {
2933         TnyList *parts;
2934         TnyIterator *iter;
2935         gint pending_purges = 0;
2936         gboolean some_purged = FALSE;
2937         ModestWindow *win = MODEST_WINDOW (user_data);
2938         if (!msg)
2939                 return;
2940
2941         /* Once the message has been retrieved for purging, we check if
2942          * it's all ok for purging */
2943
2944         parts = tny_simple_list_new ();
2945         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
2946         iter = tny_list_create_iterator (parts);
2947
2948         while (!tny_iterator_is_done (iter)) {
2949                 TnyMimePart *part;
2950                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
2951                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
2952                         if (tny_mime_part_is_purged (part))
2953                                 some_purged = TRUE;
2954                         else
2955                                 pending_purges++;
2956                 }
2957                 tny_iterator_next (iter);
2958         }
2959
2960         if (pending_purges>0) {
2961                 gint response;
2962                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
2963
2964                 if (response == GTK_RESPONSE_OK) {
2965                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
2966                         tny_iterator_first (iter);
2967                         while (!tny_iterator_is_done (iter)) {
2968                                 TnyMimePart *part;
2969                                 
2970                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
2971                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
2972                                         tny_mime_part_set_purged (part);
2973                                 tny_iterator_next (iter);
2974                         }
2975                         
2976                         tny_msg_rewrite_cache (msg);
2977                 }
2978         } else {
2979                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
2980         }
2981
2982         /* remove attachments */
2983         tny_iterator_first (iter);
2984         while (!tny_iterator_is_done (iter)) {
2985                 TnyMimePart *part;
2986                         
2987                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
2988                 g_object_unref (part);
2989                 tny_iterator_next (iter);
2990         }
2991
2992         g_object_unref (iter);
2993         g_object_unref (parts);
2994 }
2995
2996 static void
2997 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
2998                                                      ModestMainWindow *win)
2999 {
3000         GtkWidget *header_view;
3001         TnyList *header_list;
3002         TnyIterator *iter;
3003         TnyHeader *header;
3004         TnyHeaderFlags flags;
3005         ModestWindow *msg_view_window =  NULL;
3006         gboolean found;
3007
3008         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3009
3010         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3011                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3012
3013         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3014
3015         if (tny_list_get_length (header_list) == 1) {
3016                 iter = tny_list_create_iterator (header_list);
3017                 header = TNY_HEADER (tny_iterator_get_current (iter));
3018                 g_object_unref (iter);
3019         } else {
3020                 return;
3021         }
3022
3023         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3024                                                           header, &msg_view_window);
3025         flags = tny_header_get_flags (header);
3026         if (!(flags & TNY_HEADER_FLAG_CACHED))
3027                 return;
3028         if (found) {
3029                 if (msg_view_window != NULL) 
3030                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3031                 else {
3032                         /* do nothing; uid was registered before, so window is probably on it's way */
3033                         g_warning ("debug: header %p has already been registered", header);
3034                 }
3035         } else {
3036                 ModestMailOperation *mail_op = NULL;
3037                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3038                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_OPEN,
3039                                                                          G_OBJECT (win),
3040                                                                          modest_ui_actions_get_msgs_full_error_handler,
3041                                                                          NULL);
3042                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3043                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3044                 
3045                 g_object_unref (mail_op);
3046         }
3047         if (header)
3048                 g_object_unref (header);
3049         if (header_list)
3050                 g_object_unref (header_list);
3051 }
3052
3053 /*
3054  * UI handler for the "Move to" action when invoked from the
3055  * ModestMainWindow
3056  */
3057 static void 
3058 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3059                                           ModestMainWindow *win)
3060 {
3061         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3062         GtkWidget *header_view = NULL;
3063         gint result;
3064         TnyFolderStore *folder_store = NULL;
3065         ModestMailOperation *mail_op = NULL;
3066
3067         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3068
3069         /* Get the folder view */
3070         folder_view = modest_main_window_get_child_widget (win,
3071                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3072
3073         /* Get header view */
3074         header_view = modest_main_window_get_child_widget (win,
3075                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3076
3077         /* Create and run the dialog */
3078         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
3079         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3080         result = gtk_dialog_run (GTK_DIALOG(dialog));
3081         g_object_ref (tree_view);
3082
3083         /* We do this to save an indentation level ;-) */
3084         if (result != GTK_RESPONSE_ACCEPT)
3085                 goto end;
3086
3087         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3088
3089         if (TNY_IS_ACCOUNT (folder_store) && 
3090             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
3091                 goto end;
3092
3093         /* Get folder or messages to transfer */
3094         if (gtk_widget_is_focus (folder_view)) {
3095                 TnyFolderStore *src_folder;
3096                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3097
3098                 /* Clean folder on header view before moving it */
3099                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3100
3101                 if (TNY_IS_FOLDER (src_folder)) {
3102                         mail_op = 
3103                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3104                                                                                G_OBJECT(win),
3105                                                                                modest_ui_actions_move_folder_error_handler,
3106                                                                                NULL);
3107                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3108
3109                         modest_mail_operation_xfer_folder (mail_op, 
3110                                                            TNY_FOLDER (src_folder),
3111                                                            folder_store,
3112                                                            TRUE);
3113                         /* Unref mail operation */
3114                         g_object_unref (G_OBJECT (mail_op));
3115                 }
3116
3117                 /* Frees */
3118                 g_object_unref (G_OBJECT (src_folder));
3119         } else {
3120                 if (gtk_widget_is_focus (header_view)) {
3121                         TnyList *headers;
3122                         gint response;
3123
3124                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3125
3126                         /* Ask for user confirmation */
3127                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3128                                                               TNY_FOLDER (folder_store), 
3129                                                               headers);
3130
3131                         /* Transfer messages */
3132                         if (response == GTK_RESPONSE_OK) {
3133                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3134                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3135                                                                  mail_op);
3136
3137                                 modest_mail_operation_xfer_msgs (mail_op, 
3138                                                                  headers,
3139                                                                  TNY_FOLDER (folder_store),
3140                                                                  TRUE,
3141                                                                  NULL,
3142                                                                  NULL);
3143
3144                                 g_object_unref (G_OBJECT (mail_op));
3145                         }
3146                         g_object_unref (headers);
3147                 }
3148         }
3149  end:
3150         if (folder_store != NULL)
3151                 g_object_unref (folder_store);
3152         gtk_widget_destroy (dialog);
3153 }
3154
3155
3156 /*
3157  * UI handler for the "Move to" action when invoked from the
3158  * ModestMsgViewWindow
3159  */
3160 static void 
3161 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3162                                               ModestMsgViewWindow *win)
3163 {
3164         GtkWidget *dialog, *folder_view, *tree_view = NULL;
3165         gint result;
3166         ModestMainWindow *main_window;
3167         TnyHeader *header;
3168         TnyList *headers;
3169
3170         /* Get the folder view */
3171         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3172         if (main_window)
3173                 folder_view = modest_main_window_get_child_widget (main_window,
3174                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3175         else
3176                 folder_view = NULL;
3177
3178         /* Create and run the dialog */
3179         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
3180         result = gtk_dialog_run (GTK_DIALOG(dialog));
3181         g_object_ref (tree_view);
3182
3183         if (result == GTK_RESPONSE_ACCEPT) {
3184                 TnyFolderStore *folder_store;
3185                 gint response;
3186
3187                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3188
3189                 /* Create header list */
3190                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3191                         
3192                 headers = tny_simple_list_new ();
3193                 tny_list_prepend (headers, G_OBJECT (header));
3194                 g_object_unref (header);
3195
3196                 /* Ask user for confirmation. MSG-NOT404 */
3197                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3198                                                       TNY_FOLDER (folder_store), 
3199                                                       headers);
3200
3201                 /* Transfer current msg */
3202                 if (response == GTK_RESPONSE_OK) {
3203                         ModestMailOperation *mail_op;
3204
3205                         /* Create mail op */
3206                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3207                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3208                                                          mail_op);
3209                         
3210                         /* Transfer messages */
3211                         modest_mail_operation_xfer_msgs (mail_op, 
3212                                                          headers,
3213                                                          TNY_FOLDER (folder_store),
3214                                                          TRUE,
3215                                                          transfer_msgs_from_viewer_cb,
3216                                                          NULL);
3217                         g_object_unref (G_OBJECT (mail_op));
3218                 }
3219                 g_object_unref (headers);
3220                 g_object_unref (folder_store);
3221         }
3222         gtk_widget_destroy (dialog);
3223 }
3224
3225 void 
3226 modest_ui_actions_on_move_to (GtkAction *action, 
3227                               ModestWindow *win)
3228 {
3229         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3230                           MODEST_IS_MSG_VIEW_WINDOW (win));
3231
3232         if (MODEST_IS_MAIN_WINDOW (win)) 
3233                 modest_ui_actions_on_main_window_move_to (action, 
3234                                                           MODEST_MAIN_WINDOW (win));
3235         else
3236                 modest_ui_actions_on_msg_view_window_move_to (action, 
3237                                                               MODEST_MSG_VIEW_WINDOW (win));
3238 }
3239
3240 /*
3241  * Calls #HeadersFunc for each header already selected in the main
3242  * window or the message currently being shown in the msg view window
3243  */
3244 static void
3245 do_headers_action (ModestWindow *win, 
3246                    HeadersFunc func,
3247                    gpointer user_data)
3248 {
3249         TnyList *headers_list;
3250         TnyIterator *iter;
3251         TnyHeader *header;
3252         TnyFolder *folder;
3253
3254         /* Get headers */
3255         headers_list = get_selected_headers (win);
3256         if (!headers_list)
3257                 return;
3258
3259         /* Get the folder */
3260         iter = tny_list_create_iterator (headers_list);
3261         header = TNY_HEADER (tny_iterator_get_current (iter));
3262         folder = tny_header_get_folder (header);
3263         g_object_unref (header);
3264
3265         /* Call the function for each header */
3266         while (!tny_iterator_is_done (iter)) {
3267                 header = TNY_HEADER (tny_iterator_get_current (iter));
3268                 func (header, win, user_data);
3269                 g_object_unref (header);
3270                 tny_iterator_next (iter);
3271         }
3272
3273         /* Trick: do a poke status in order to speed up the signaling
3274            of observers */
3275         tny_folder_poke_status (folder);
3276
3277         /* Frees */
3278         g_object_unref (folder);
3279         g_object_unref (iter);
3280         g_object_unref (headers_list);
3281 }
3282
3283 void 
3284 modest_ui_actions_view_attachment (GtkAction *action,
3285                                    ModestWindow *window)
3286 {
3287         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3288                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3289         } else {
3290                 /* not supported window for this action */
3291                 g_return_if_reached ();
3292         }
3293 }
3294
3295 void
3296 modest_ui_actions_save_attachments (GtkAction *action,
3297                                     ModestWindow *window)
3298 {
3299         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3300                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3301         } else {
3302                 /* not supported window for this action */
3303                 g_return_if_reached ();
3304         }
3305 }
3306
3307 void
3308 modest_ui_actions_remove_attachments (GtkAction *action,
3309                                       ModestWindow *window)
3310 {
3311         if (MODEST_IS_MAIN_WINDOW (window)) {
3312                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3313         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3314                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3315         } else {
3316                 /* not supported window for this action */
3317                 g_return_if_reached ();
3318         }
3319 }
3320
3321 void 
3322 modest_ui_actions_on_settings (GtkAction *action, 
3323                                ModestWindow *win)
3324 {
3325         GtkWidget *dialog;
3326
3327         dialog = modest_platform_get_global_settings_dialog ();
3328         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3329         gtk_widget_show_all (dialog);
3330
3331         gtk_dialog_run (GTK_DIALOG (dialog));
3332
3333         gtk_widget_destroy (dialog);
3334 }
3335
3336 void 
3337 modest_ui_actions_on_help (GtkAction *action, 
3338                            ModestWindow *win)
3339 {
3340         const gchar *help_id = NULL;
3341
3342         if (MODEST_IS_MAIN_WINDOW (win)) {
3343                 const gchar *action_name;
3344                 action_name = gtk_action_get_name (action);
3345
3346                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3347                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3348                         GtkWidget *folder_view;
3349                         TnyFolderStore *folder_store;
3350                         /* Get selected folder */
3351                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3352                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3353                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3354
3355                         /* Switch help_id */
3356                         if (TNY_IS_FOLDER (folder_store)) {
3357                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3358                                 case TNY_FOLDER_TYPE_NORMAL:
3359                                         help_id = "applications_email_userfolder";
3360                                         break;
3361                                 case TNY_FOLDER_TYPE_INBOX:
3362                                         help_id = "applications_email_inbox";
3363                                         break;
3364                                 case TNY_FOLDER_TYPE_OUTBOX:
3365                                         help_id = "applications_email_outbox";
3366                                         break;
3367                                 case TNY_FOLDER_TYPE_SENT:
3368                                         help_id = "applications_email_sent";
3369                                         break;
3370                                 case TNY_FOLDER_TYPE_DRAFTS:
3371                                         help_id = "applications_email_drafts";
3372                                         break;
3373                                 case TNY_FOLDER_TYPE_ARCHIVE:
3374                                         help_id = "applications_email_archive";
3375                                         break;
3376                                 default:
3377                                         help_id = NULL;
3378                                 }
3379                         }
3380                         g_object_unref (folder_store);
3381                 } else {
3382                         help_id = "applications_email_mainview";        
3383                 }
3384         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3385                 help_id = "applications_email_viewer";
3386         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3387                 help_id = "applications_email_editor";
3388
3389         modest_platform_show_help (GTK_WINDOW (win), help_id);
3390 }
3391
3392 void 
3393 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3394                                             ModestWindow *window)
3395 {
3396         ModestMailOperation *mail_op;
3397         TnyList *headers;
3398
3399         /* Get headers */
3400         headers = get_selected_headers (window);
3401         if (!headers)
3402                 return;
3403
3404         /* Create mail operation */
3405         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3406                                                                  G_OBJECT (window),
3407                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3408                                                                  NULL);
3409         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3410         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3411
3412         /* Frees */
3413         g_object_unref (headers);
3414         g_object_unref (mail_op);
3415 }
3416
3417 void
3418 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3419                                           ModestWindow *window)
3420 {
3421         g_return_if_fail (MODEST_IS_WINDOW (window));
3422
3423         /* Update dimmed */     
3424         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3425 }
3426
3427 void
3428 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3429                                           ModestWindow *window)
3430 {
3431         g_return_if_fail (MODEST_IS_WINDOW (window));
3432
3433         /* Update dimmed */     
3434         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3435 }
3436
3437 void
3438 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3439                                           ModestWindow *window)
3440 {
3441         g_return_if_fail (MODEST_IS_WINDOW (window));
3442
3443         /* Update dimmed */     
3444         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3445 }
3446
3447 void
3448 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3449                                           ModestWindow *window)
3450 {
3451         g_return_if_fail (MODEST_IS_WINDOW (window));
3452
3453         /* Update dimmed */     
3454         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3455 }
3456
3457 void
3458 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3459                                           ModestWindow *window)
3460 {
3461         g_return_if_fail (MODEST_IS_WINDOW (window));
3462
3463         /* Update dimmed */     
3464         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3465 }
3466
3467 void
3468 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3469                                                  ModestWindow *window)
3470 {
3471         g_return_if_fail (MODEST_IS_WINDOW (window));
3472
3473         /* Update dimmed */     
3474         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3475 }
3476
3477 void
3478 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3479                                                      ModestWindow *window)
3480 {
3481         g_return_if_fail (MODEST_IS_WINDOW (window));
3482
3483         /* Update dimmed */     
3484         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3485 }
3486
3487 void
3488 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3489                                                      ModestWindow *window)
3490 {
3491         g_return_if_fail (MODEST_IS_WINDOW (window));
3492
3493         /* Update dimmed */     
3494         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3495 }
3496
3497 void
3498 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3499 {
3500         g_return_if_fail (MODEST_IS_WINDOW (window));
3501
3502         /* Update dimmed */     
3503         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3504 }
3505
3506 void
3507 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3508 {
3509         g_return_if_fail (MODEST_IS_WINDOW (window));
3510
3511         modest_platform_show_search_messages (GTK_WINDOW (window));
3512 }
3513
3514 void     
3515 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3516 {
3517         g_return_if_fail (MODEST_IS_WINDOW (win));
3518         modest_platform_show_addressbook (GTK_WINDOW (win));
3519 }
3520
3521
3522 void
3523 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3524                                           ModestWindow *window)
3525 {
3526         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3527
3528         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3529 }
3530
3531 static void 
3532 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3533                                    ModestMailOperationState *state,
3534                                    gpointer user_data)
3535 {
3536         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3537
3538         /* Set send/receive operation finished */       
3539         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3540                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3541         
3542 }
3543
3544