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