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