[balsa/gtk3] Port main-window to GtkApplicationWindow etc.



commit 41fb9ae9b5e14ebd9220c70c5da83b01d0703703
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Mon Jul 22 21:42:55 2013 -0400

    Port main-window to GtkApplicationWindow etc.
    
        Make main-window a GtkApplicationWindow, and port menus from
        GtkUIManager to GtkBuilder and from GtkAction to GAction
    
        * src/main-window.c (balsa_window_get_toolbar_model),
        (bw_action_set_boolean), (bw_action_get_boolean),
        (bw_action_set_string), (bw_action_set_enabled),
        (bw_app_action_set_enabled), (bw_actions_set_enabled),
        (toggle_activated), (radio_activated), (bw_show_or_hide_widget),
        (new_message_activated), (new_mbox_activated),
        (new_maildir_activated), (new_mh_activated),
        (new_imap_box_activated), (new_imap_folder_activated),
        (new_imap_subfolder_activated), (address_book_activated),
        (prefs_activated), (help_activated), (about_activated),
        (quit_activated), (continue_activated), (get_new_mail_activated),
        (send_queued_mail_activated), (send_and_receive_mail_activated),
        (page_setup_activated), (print_activated), (copy_activated),
        (select_all_activated), (select_thread_activated),
        (find_activated), (find_next_activated),
        (find_in_message_activated), (filters_activated),
        (export_filters_activated), (expand_all_activated),
        (collapse_all_activated), (zoom_in_activated),
        (zoom_out_activated), (zoom_normal_activated),
        (next_message_activated), (previous_message_activated),
        (next_unread_activated), (next_flagged_activated),
        (reset_filter_activated), (mailbox_select_all_activated),
        (mailbox_edit_activated), (mailbox_delete_activated),
        (mailbox_expunge_activated), (mailbox_close_activated),
        (empty_trash_activated), (select_filters_activated),
        (remove_duplicates_activated), (reply_activated),
        (reply_all_activated), (reply_group_activated),
        (forward_attached_activated), (forward_inline_activated),
        (pipe_activated), (next_part_activated), (previous_part_activated),
        (save_part_activated), (view_source_activated),
        (copy_message_activated), (select_text_activated),
        (move_to_trash_activated), (toggle_flag),
        (toggle_flagged_activated), (toggle_deleted_activated),
        (toggle_new_activated), (toggle_answered_activated),
        (store_address_activated), (show_mailbox_tree_change_state),
        (show_mailbox_tabs_change_state), (show_toolbar_change_state),
        (show_statusbar_change_state), (show_sos_bar_change_state),
        (wrap_change_state), (hide_change_state),
        (bw_reset_show_all_headers), (header_change_state),
        (threading_change_state), (bw_set_menus), (bw_enable_next_unread),
        (balsa_window_new), (bw_enable_expand_collapse),
        (bw_next_unread_mailbox), (bw_enable_mailbox_menus),
        (balsa_window_update_book_menus), (bw_enable_message_menus),
        (bw_enable_edit_menus), (bw_enable_view_menus),
        (enable_empty_trash), (balsa_window_enable_continue),

 ChangeLog             |   90 ++
 src/main-window.c     | 3705 +++++++++++++++++++++----------------------------
 src/main-window.h     |   11 +-
 src/message-window.c  |    2 +-
 src/sendmsg-window.c  |    2 +-
 src/toolbar-factory.c |  122 ++-
 src/toolbar-factory.h |   12 +-
 src/toolbar-prefs.c   |    6 +-
 8 files changed, 1814 insertions(+), 2136 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8f634da..519655b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,95 @@
 2013-07-22  Peter Bloomfield
 
+       Make main-window a GtkApplicationWindow, and port menus from
+       GtkUIManager to GtkBuilder and from GtkAction to GAction
+
+       * src/main-window.c (balsa_window_get_toolbar_model),
+       (bw_action_set_boolean), (bw_action_get_boolean),
+       (bw_action_set_string), (bw_action_set_enabled),
+       (bw_app_action_set_enabled), (bw_actions_set_enabled),
+       (toggle_activated), (radio_activated), (bw_show_or_hide_widget),
+       (new_message_activated), (new_mbox_activated),
+       (new_maildir_activated), (new_mh_activated),
+       (new_imap_box_activated), (new_imap_folder_activated),
+       (new_imap_subfolder_activated), (address_book_activated),
+       (prefs_activated), (help_activated), (about_activated),
+       (quit_activated), (continue_activated), (get_new_mail_activated),
+       (send_queued_mail_activated), (send_and_receive_mail_activated),
+       (page_setup_activated), (print_activated), (copy_activated),
+       (select_all_activated), (select_thread_activated),
+       (find_activated), (find_next_activated),
+       (find_in_message_activated), (filters_activated),
+       (export_filters_activated), (expand_all_activated),
+       (collapse_all_activated), (zoom_in_activated),
+       (zoom_out_activated), (zoom_normal_activated),
+       (next_message_activated), (previous_message_activated),
+       (next_unread_activated), (next_flagged_activated),
+       (reset_filter_activated), (mailbox_select_all_activated),
+       (mailbox_edit_activated), (mailbox_delete_activated),
+       (mailbox_expunge_activated), (mailbox_close_activated),
+       (empty_trash_activated), (select_filters_activated),
+       (remove_duplicates_activated), (reply_activated),
+       (reply_all_activated), (reply_group_activated),
+       (forward_attached_activated), (forward_inline_activated),
+       (pipe_activated), (next_part_activated), (previous_part_activated),
+       (save_part_activated), (view_source_activated),
+       (copy_message_activated), (select_text_activated),
+       (move_to_trash_activated), (toggle_flag),
+       (toggle_flagged_activated), (toggle_deleted_activated),
+       (toggle_new_activated), (toggle_answered_activated),
+       (store_address_activated), (show_mailbox_tree_change_state),
+       (show_mailbox_tabs_change_state), (show_toolbar_change_state),
+       (show_statusbar_change_state), (show_sos_bar_change_state),
+       (wrap_change_state), (hide_change_state),
+       (bw_reset_show_all_headers), (header_change_state),
+       (threading_change_state), (bw_set_menus), (bw_enable_next_unread),
+       (balsa_window_new), (bw_enable_expand_collapse),
+       (bw_next_unread_mailbox), (bw_enable_mailbox_menus),
+       (balsa_window_update_book_menus), (bw_enable_message_menus),
+       (bw_enable_edit_menus), (bw_enable_view_menus),
+       (enable_empty_trash), (balsa_window_enable_continue),
+       (bw_enable_part_menu_items), (bw_set_threading_menu),
+       (bw_set_filter_menu), (bw_filter_to_int),
+       (bw_get_condition_from_int), (balsa_window_open_mbnode),
+       (balsa_window_close_mbnode), (bw_notebook_label_style),
+       (bw_mailbox_changed), (bw_notebook_label_notify),
+       (bw_notebook_label_new), (bw_real_open_mbnode_idle_cb),
+       (bw_real_open_mbnode_thread), (balsa_window_real_open_mbnode),
+       (bw_focus_idle), (balsa_window_real_close_mbnode),
+       (balsa_identities_changed), (bw_close_mailbox_on_timer),
+       (balsa_window_destroy), (balsa_window_refresh),
+       (bw_register_open_mailbox), (bw_unregister_open_mailbox),
+       (bw_is_open_mailbox), (bw_check_mailbox_list),
+       (bw_add_mbox_to_checklist), (bw_imap_check_test),
+       (bw_progress_dialog_destroy_cb), (bw_progress_dialog_response_cb),
+       (ensure_check_mail_dialog), (bw_mailbox_check),
+       (check_new_messages_real), (bw_check_new_messages),
+       (check_new_messages_count), (bw_check_messages_thread_idle_cb),
+       (bw_check_messages_thread), (mail_progress_notify_cb),
+       (send_progress_notify_cb),
+       (bw_get_new_message_notification_string),
+       (bw_display_new_mail_notification),
+       (mw_mbox_change_connection_status),
+       (bw_change_connection_status_idle),
+       (balsa_window_find_current_index), (bw_open_mailbox_cb),
+       (bw_find_real), (bw_hide_changed_set_view_filter),
+       (bw_reset_filter), (update_view_menu),
+       (balsa_window_set_statusbar), (balsa_window_next_unread):
+       * src/main-window.h: BalsaWindow now subclasses
+       GtkApplicationWindow.
+       * src/message-window.c (message_window_new): use new toolbar
+       API.
+       * src/sendmsg-window.c (sendmsg_window_new): ditto.
+       * src/toolbar-factory.c (balsa_toolbar_model_add_entries),
+       (tm_has_second_line), (tm_changed_cb), (tm_changed_old_cb),
+       (tm_toolbar_weak_notify), (tm_realize_cb), (balsa_toolbar_new):
+       main-window has a GActionMap, not a GtkUIManager.
+       * src/toolbar-factory.h: temporary API.
+       * src/toolbar-prefs.c (customize_dialog_cb),
+       (create_toolbar_page): temporary transition code.
+
+2013-07-22  Peter Bloomfield
+
        * src/balsa-icons.c (load_balsa_pixmap): do not leak pixbuf.
 
 2013-07-22  Peter Bloomfield
diff --git a/src/main-window.c b/src/main-window.c
index 331f00b..754adc5 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -18,7 +18,7 @@
  */
 
 /*
- * BalsaWindow: subclass of GtkWindow
+ * BalsaWindow: subclass of GtkApplicationWindow
  *
  * The only known instance of BalsaWindow is balsa_app.main_window,
  * but the code in this module does not depend on that fact, to make it
@@ -137,6 +137,8 @@ static gboolean bw_imap_check_test(const gchar * path);
 
 static void bw_enable_mailbox_menus(BalsaWindow * window, BalsaIndex * index);
 static void bw_enable_message_menus(BalsaWindow * window, guint msgno);
+static void bw_enable_expand_collapse(BalsaWindow * window,
+                                      LibBalsaMailbox * mailbox);
 #ifdef HAVE_HTML_WIDGET
 static void bw_enable_view_menus(BalsaWindow * window, BalsaMessage * bm);
 #endif                         /* HAVE_HTML_WIDGET */
@@ -144,104 +146,15 @@ static void bw_register_open_mailbox(LibBalsaMailbox *m);
 static void bw_unregister_open_mailbox(LibBalsaMailbox *m);
 static gboolean bw_is_open_mailbox(LibBalsaMailbox *m);
 
-/* dialogs */
-static void bw_show_about_box(GtkAction *, gpointer data);
-
-/* callbacks */
-static void bw_send_outbox_messages_cb    (GtkAction *, gpointer data);
-static void bw_send_receive_messages_cb   (GtkAction *, gpointer data);
-static void bw_page_setup_cb              (GtkAction * action, gpointer data);
-static void bw_message_print_cb           (GtkAction * action, gpointer data);
-
-static void bw_new_message_cb             (GtkAction * action, gpointer data);
-static void bw_replyto_message_cb         (GtkAction * action, gpointer data);
-static void bw_replytoall_message_cb      (GtkAction * action, gpointer data);
-static void bw_replytogroup_message_cb    (GtkAction * action, gpointer data);
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_forward_message_attached_cb(GtkAction * action, gpointer data);
-static void bw_forward_message_inline_cb  (GtkAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-static void bw_forward_message_default_cb (GtkAction * action, gpointer data);
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_pipe_message_cb            (GtkAction * action, gpointer data);
-static void bw_select_thread_cb           (GtkAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-static void bw_continue_message_cb        (GtkAction * action, gpointer data);
-
-static void bw_next_message_cb            (GtkAction * action, gpointer data);
-static void bw_next_unread_message_cb     (GtkAction * action, gpointer data);
-static void bw_next_flagged_message_cb    (GtkAction * action, gpointer data);
-static void bw_previous_message_cb        (GtkAction * action, gpointer data);
-
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_next_part_cb               (GtkAction * action, gpointer data);
-static void bw_previous_part_cb           (GtkAction * action, gpointer data);
-#endif
-static void bw_save_current_part_cb       (GtkAction * action, gpointer data);
-static void bw_view_msg_source_cb         (GtkAction * action, gpointer data);
-
-static void bw_trash_message_cb           (GtkAction * action, gpointer data);
-static void bw_toggle_flagged_message_cb  (GtkAction * action, gpointer data);
-static void bw_toggle_deleted_message_cb  (GtkAction * action, gpointer data);
-static void bw_toggle_new_message_cb      (GtkAction * action, gpointer data);
-static void bw_toggle_answered_message_cb (GtkAction * action, gpointer data);
-static void bw_store_address_cb           (GtkAction * action, gpointer data);
-static void bw_empty_trash_cb             (GtkAction * action, gpointer data);
-
-static void bw_header_activate_cb         (GtkAction * action, gpointer data);
-static void bw_expand_all_cb              (GtkAction * action, gpointer data);
-static void bw_collapse_all_cb            (GtkAction * action, gpointer data);
-#ifdef HAVE_HTML_WIDGET
-static void bw_zoom_in_cb                 (GtkAction * action, gpointer data);
-static void bw_zoom_out_cb                (GtkAction * action, gpointer data);
-static void bw_zoom_100_cb                (GtkAction * action, gpointer data);
-#endif                         /* HAVE_HTML_WIDGET */
-
-static void bw_copy_cb                    (GtkAction * action, gpointer data);
-static void bw_select_all_cb              (GtkAction * action, gpointer data);
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_message_copy_cb            (GtkAction * action, gpointer data);
-static void bw_message_select_all_cb      (GtkAction * action, gpointer data);
-static void bw_find_in_message_cb         (GtkAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-static void bw_mark_all_cb                (GtkAction * action, gpointer data);
-
-static void bw_find_cb                    (GtkAction * action, gpointer data);
-static void bw_find_again_cb              (GtkAction * action, gpointer data);
-static void bw_filter_dlg_cb              (GtkAction * action, gpointer data);
-static void bw_filter_export_cb           (GtkAction * action, gpointer data);
-static void bw_filter_run_cb              (GtkAction * action, gpointer data);
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_remove_duplicates_cb       (GtkAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-
-static void bw_mailbox_close_cb           (GtkAction * action, gpointer data);
-
-static void bw_reset_filter_cb            (GtkAction * action, gpointer data);
-static void bw_mailbox_expunge_cb         (GtkAction * action, gpointer data);
 static void bw_mailbox_tab_close_cb(GtkWidget * widget, gpointer data);
 
 #if defined(ENABLE_TOUCH_UI)
-static void bw_sort_change_cb(GtkRadioAction * action,
-                              GtkRadioAction * current, gpointer data);
-static void bw_toggle_order_cb(GtkToggleAction * action, gpointer data);
 static void bw_set_sort_menu(BalsaWindow *window,
                              LibBalsaMailboxSortFields col,
                              LibBalsaMailboxSortType   order);
 #endif /* ENABLE_TOUCH_UI */
-static void bw_hide_changed_cb         (GtkToggleAction * action, gpointer data);
-static void bw_wrap_message_cb         (GtkToggleAction * action, gpointer data);
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_show_toolbar_cb         (GtkToggleAction * action, gpointer data);
-static void bw_show_statusbar_cb       (GtkToggleAction * action, gpointer data);
-static void bw_show_sos_bar_cb         (GtkToggleAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-static void bw_show_all_headers_tool_cb(GtkToggleAction * action, gpointer data);
-static void bw_show_preview_pane_cb    (GtkToggleAction * action, gpointer data);
-static void bw_reset_show_all_headers(BalsaWindow * window);
 
 #if !defined(ENABLE_TOUCH_UI)
-static void bw_threading_activate_cb(GtkAction * action, gpointer data);
 static void bw_set_threading_menu(BalsaWindow * window, int option);
 static void bw_show_mbtree(BalsaWindow * window);
 #endif /* ENABLE_TOUCH_UI */
@@ -249,21 +162,13 @@ static void bw_set_filter_menu(BalsaWindow * window, int gui_filter);
 static LibBalsaCondition *bw_get_view_filter(BalsaWindow * window);
 #if defined(ENABLE_TOUCH_UI)
 static gboolean bw_open_mailbox_cb(GtkWidget *w, GdkEventKey *e, gpointer data);
-static void bw_enable_view_filter_cb(GtkToggleAction * action, gpointer data);
 #endif /* ENABLE_TOUCH_UI */
 
-static void bw_address_book_cb(GtkWindow *widget, gpointer data);
-
 static void bw_select_part_cb(BalsaMessage * bm, gpointer data);
 
 static void bw_find_real(BalsaWindow * window, BalsaIndex * bindex,
                          gboolean again);
 
-#if !defined(ENABLE_TOUCH_UI)
-static void bw_show_mbtree_cb(GtkToggleAction * action, gpointer data);
-static void bw_show_mbtabs_cb(GtkToggleAction * action, gpointer data);
-#endif /* ENABLE_TOUCH_UI */
-
 static void bw_notebook_size_allocate_cb(GtkWidget * notebook,
                                          GtkAllocation * alloc,
                                          BalsaWindow * bw);
@@ -291,23 +196,8 @@ static gboolean bw_notebook_drag_motion_cb(GtkWidget* widget,
 
 
 static GtkWidget *bw_notebook_label_new (BalsaMailboxNode* mbnode);
-static void bw_ident_manage_dialog_cb(GtkAction * action, gpointer user_data);
+static void bw_reset_filter(BalsaWindow * bw);
 
-static void bw_contents_cb(GtkAction * action, gpointer user_data);
-static void bw_mailbox_tab_n_cb(GtkAction * action, gpointer data);
-
-static void
-bw_quit_nicely(GtkAction * action, gpointer data)
-{
-    GdkEventAny e = { GDK_DELETE, NULL, 0 };
-    e.window = gtk_widget_get_window(GTK_WIDGET(data));
-    libbalsa_information_parented(GTK_WINDOW(data),
-                                  LIBBALSA_INFORMATION_MESSAGE,
-                         _("Balsa closes files and connections. Please wait..."));
-    while(gtk_events_pending())
-        gtk_main_iteration_do(FALSE);
-    gdk_event_put((GdkEvent*)&e);
-}
 
 /* ===================================================================
    Balsa menus. Touchpad has some simplified menus which do not
@@ -316,651 +206,7 @@ bw_quit_nicely(GtkAction * action, gpointer data)
    proponents of GNOME2 dumbify approach (OK, I am bit unfair here).
 */
 
-#if HAVE_MACOSX_DESKTOP
-#define MAC_MODIFIER    "<alt>"
-#else
-#define MAC_MODIFIER
-#endif
-
-/* Actions that are always sensitive: */
-static const GtkActionEntry entries[] = {
-    /* Menus */
-    {"FileMenu", NULL, N_("_File")},
-    {"EditMenu", NULL, N_("_Edit")},
-    {"ViewMenu", NULL, N_("_View")},
-    {"MailboxMenu", NULL, N_("Mail_box")},
-    {"MessageMenu", NULL, N_("_Message")},
-    {"SettingsMenu", NULL, N_("_Settings")},
-    {"HelpMenu", NULL, N_("_Help")},
-#if !defined(ENABLE_TOUCH_UI)
-    {"FileNewMenu", NULL, N_("_New")},
-    {"MailboxTabMenu", NULL, NULL},
-#else  /* ENABLE_TOUCH_UI */
-    {"MailboxesMenu", NULL, N_("Mail_boxes")},
-    /* Less frequently used entries of the 'View' menu */
-    {"ViewMoreMenu", NULL, N_("_More")},
-    {"ShownHeadersMenu", NULL, N_("_Headers")},
-    {"SortMenu", NULL, N_("_Sort Mailbox")},
-    {"HideMessagesMenu", NULL, N_("H_ide messages")},
-    /* Less frequently used entries of the 'Message' menu */
-    {"MessageMoreMenu", NULL, N_("_More")},
-    {"ToolsMenu", NULL, N_("_Tools")},
-    {"ToolsFiltersMenu", NULL, N_("_Filters")},
-    {"ManageFilters", "document-properties", N_("F_ilters"), NULL,
-     N_("Manage filters"), G_CALLBACK(bw_filter_dlg_cb)},
-#endif /* ENABLE_TOUCH_UI */
-    /* File menu items */
-    /* Not in the touchpad menu, but still available as a toolbar
-     * button: */
-    {"Continue", BALSA_PIXMAP_CONTINUE, N_("_Continue"), MAC_MODIFIER "C",
-     N_("Continue editing current message"),
-     G_CALLBACK(bw_continue_message_cb)},
-    {"GetNewMail", BALSA_PIXMAP_RECEIVE, N_("_Get New Mail"), "<control>M",
-     N_("Fetch new incoming mail"), G_CALLBACK(check_new_messages_cb)},
-    {"SendQueuedMail", BALSA_PIXMAP_SEND, N_("_Send Queued Mail"),
-     "<control>T", N_("Send messages from the outbox"),
-     G_CALLBACK(bw_send_outbox_messages_cb)},
-    {"SendAndReceiveMail", BALSA_PIXMAP_SEND_RECEIVE,
-     N_("Send and _Receive Mail"), "<control>B",
-     N_("Send and Receive messages"),
-     G_CALLBACK(bw_send_receive_messages_cb)},
-    {"PageSetup", NULL, N_("Page _Setup"), NULL,
-     N_("Set up page for printing"), G_CALLBACK(bw_page_setup_cb)},
-    {"AddressBook", BALSA_PIXMAP_BOOK_RED, N_("_Address Book..."), MAC_MODIFIER "B",
-     N_("Open the address book"), G_CALLBACK(bw_address_book_cb)},
-    {"Quit", "application-exit", N_("_Quit"), "<control>Q", N_("Quit Balsa"),
-     G_CALLBACK(bw_quit_nicely)},
-    /* File:New submenu items */
-    {"NewMessage", BALSA_PIXMAP_COMPOSE, N_("_Message..."), MAC_MODIFIER "M",
-     N_("Compose a new message"), G_CALLBACK(bw_new_message_cb)},
-#if !defined(ENABLE_TOUCH_UI)
-    {"NewMbox", "list-add", N_("Local mbox mailbox..."), NULL,
-     N_("Add a new mbox style mailbox"),
-     G_CALLBACK(mailbox_conf_add_mbox_cb)},
-    {"NewMaildir", "list-add", N_("Local Maildir mailbox..."), NULL,
-     N_("Add a new Maildir style mailbox"),
-     G_CALLBACK(mailbox_conf_add_maildir_cb)},
-    {"NewMH", "list-add", N_("Local MH mailbox..."), NULL,
-     N_("Add a new MH style mailbox"), G_CALLBACK(mailbox_conf_add_mh_cb)},
-#else  /* ENABLE_TOUCH_UI */
-    {"NewMbox", "list-add", N_("New mailbox..."), NULL,
-     N_("Add a new mbox style mailbox"),
-     G_CALLBACK(mailbox_conf_add_mbox_cb)},
-    {"NewMaildir", "list-add", N_("New \"Maildir\" mailbox..."), NULL,
-     N_("Add a new Maildir style mailbox"),
-     G_CALLBACK(mailbox_conf_add_maildir_cb)},
-    {"NewMH", "list-add", N_("New \"MH\" mailbox..."), NULL,
-     N_("Add a new MH style mailbox"), G_CALLBACK(mailbox_conf_add_mh_cb)},
-#endif /* ENABLE_TOUCH_UI */
-    {"NewIMAPBox", "list-add", N_("Remote IMAP mailbox..."), NULL,
-     N_("Add a new IMAP mailbox"), G_CALLBACK(mailbox_conf_add_imap_cb)},
-    {"NewIMAPFolder", "list-add", N_("Remote IMAP folder..."), NULL,
-     N_("Add a new IMAP folder"), G_CALLBACK(folder_conf_add_imap_cb)},
-    {"NewIMAPSubfolder", "list-add", N_("Remote IMAP subfolder..."),
-     NULL, N_("Add a new IMAP subfolder"),
-     G_CALLBACK(folder_conf_add_imap_sub_cb)},
-    /* Edit menu items */
-    {"Copy", "edit-copy", N_("_Copy"), "<control>C", NULL,
-     G_CALLBACK(bw_copy_cb)},
-    {"Filters", "document-properties", N_("F_ilters..."), NULL,
-     N_("Manage filters"), G_CALLBACK(bw_filter_dlg_cb)},
-    /* Export selected filters to a text file. */
-    {"ExportFilters", "document-properties", N_("_Export Filters..."), NULL,
-     N_("Export filters as Sieve scripts"), G_CALLBACK(bw_filter_export_cb)},
-    {"Preferences", "preferences-system", N_("Prefere_nces"), NULL, NULL,
-     G_CALLBACK(open_preferences_manager)},
-    /* View menu items */
-    {"ExpandAll", NULL, N_("E_xpand All"), "<control>E",
-     N_("Expand all threads"), G_CALLBACK(bw_expand_all_cb)},
-    {"CollapseAll", NULL, N_("_Collapse All"), "<control>L",
-     N_("Collapse all expanded threads"), G_CALLBACK(bw_collapse_all_cb)},
-#ifdef HAVE_HTML_WIDGET
-    {"ZoomIn", "zoom-in", N_("Zoom _In"), "<control>plus",
-     N_("Increase magnification"), G_CALLBACK(bw_zoom_in_cb)},
-    {"ZoomOut", "zoom-out", N_("Zoom _Out"), "<control>minus",
-     N_("Decrease magnification"), G_CALLBACK(bw_zoom_out_cb)},
-    /* To warn msgfmt that the % sign isn't a format specifier: */
-    /* xgettext:no-c-format */
-    {"Zoom100", "zoom-original", N_("Zoom _100%"), NULL,
-     N_("No magnification"), G_CALLBACK(bw_zoom_100_cb)},
-#endif                          /* HAVE_HTML_WIDGET */
-    /* Mailbox menu item that does not require a mailbox */
-    {"NextUnread", BALSA_PIXMAP_NEXT_UNREAD, N_("Next Unread Message"),
-     "<control>N", N_("Next Unread Message"),
-     G_CALLBACK(bw_next_unread_message_cb)},
-    {"EmptyTrash", "list-remove", N_("Empty _Trash"), NULL,
-     N_("Delete messages from the Trash mailbox"),
-     G_CALLBACK(bw_empty_trash_cb)},
-    /* Settings menu items */
-    {"Toolbars", "system-run", N_("_Toolbars..."), NULL,
-     N_("Customize toolbars"), G_CALLBACK(customize_dialog_cb)},
-    {"Identities", BALSA_PIXMAP_IDENTITY, N_("_Identities..."), NULL,
-     N_("Create and set current identities"),
-     G_CALLBACK(bw_ident_manage_dialog_cb)},
-    /* Help menu items */
-    {"TableOfContents", "help-browser", N_("_User's Guide"), "F1",
-     N_("Table of Contents"), G_CALLBACK(bw_contents_cb)},
-    {"MailboxTab1", NULL, NULL, "<alt>1", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab2", NULL, NULL, "<alt>2", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab3", NULL, NULL, "<alt>3", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab4", NULL, NULL, "<alt>4", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab5", NULL, NULL, "<alt>5", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab6", NULL, NULL, "<alt>6", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab7", NULL, NULL, "<alt>7", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab8", NULL, NULL, "<alt>8", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab9", NULL, NULL, "<alt>9", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"MailboxTab0", NULL, NULL, "<alt>0", NULL,
-     G_CALLBACK(bw_mailbox_tab_n_cb)},
-    {"About", "help-about", N_("_About"), NULL, N_("About Balsa"),
-     G_CALLBACK(bw_show_about_box)}
-};
-
-/* Actions that are sensitive only when a mailbox is selected: */
-static const GtkActionEntry mailbox_entries[] = {
-    /* Edit menu items */
-    {"SelectAll", NULL, N_("Select _All"), "<control>A", NULL,
-     G_CALLBACK(bw_select_all_cb)},
-    {"Find", "edit-find", N_("_Find"), "<control>F", NULL,
-     G_CALLBACK(bw_find_cb)},
-    {"FindNext", "edit-find", N_("Find Ne_xt"), "<control>G", NULL,
-     G_CALLBACK(bw_find_again_cb)},
-    /* Mailbox menu items */
-    {"NextMessage", BALSA_PIXMAP_NEXT, N_("Next Message"), MAC_MODIFIER "N",
-     N_("Next Message"), G_CALLBACK(bw_next_message_cb)},
-    {"PreviousMessage", BALSA_PIXMAP_PREVIOUS, N_("Previous Message"), MAC_MODIFIER "P",
-     N_("Previous Message"), G_CALLBACK(bw_previous_message_cb)},
-    {"NextFlagged", BALSA_PIXMAP_NEXT_FLAGGED, N_("Next Flagged Message"),
-     "<control><alt>F", N_("Next Flagged Message"),
-     G_CALLBACK(bw_next_flagged_message_cb)},
-    {"MailboxHideMenu", NULL, N_("_Hide Messages")},
-    {"ResetFilter", "gtk-cancel", N_("_Reset Filter"), NULL,
-     N_("Reset mailbox filter"), G_CALLBACK(bw_reset_filter_cb)},
-    {"MailboxSelectAll", BALSA_PIXMAP_MARK_ALL, N_("_Select All"), NULL,
-     N_("Select all messages in current mailbox"),
-     G_CALLBACK(bw_mark_all_cb)},
-    {"MailboxEdit", "preferences-system", N_("_Properties..."), NULL,
-     N_("Edit the selected mailbox"), G_CALLBACK(mailbox_conf_edit_cb)},
-    {"MailboxDelete", "list-remove", N_("_Delete..."), NULL,
-     N_("Delete the selected mailbox"),
-     G_CALLBACK(mailbox_conf_delete_cb)},
-#if !defined(ENABLE_TOUCH_UI)
-    {"Expunge", "edit-clear", N_("E_xpunge Deleted Messages"), NULL,
-     N_("Expunge messages marked as deleted in the current mailbox"),
-#else  /* ENABLE_TOUCH_UI */
-    {"Expunge", "list-remove", N_("E_xpunge Deleted Messages"), NULL,
-     N_("Expunge messages marked as deleted in the current mailbox"),
-#endif /* ENABLE_TOUCH_UI */
-     G_CALLBACK(bw_mailbox_expunge_cb)},
-    {"Close", "window-close", N_("_Close"), NULL, N_("Close mailbox"),
-     G_CALLBACK(bw_mailbox_close_cb)},
-    {"SelectFilters", "document-properties", N_("Select _Filters"), NULL,
-     N_("Select filters to be applied automatically to current mailbox"),
-     G_CALLBACK(bw_filter_run_cb)},
-#if !defined(ENABLE_TOUCH_UI)
-    {"RemoveDuplicates", "list-remove", N_("_Remove Duplicates"), NULL,
-     N_("Remove duplicated messages from the current mailbox"),
-     G_CALLBACK(bw_remove_duplicates_cb)}
-#endif /* ENABLE_TOUCH_UI */
-};
-
-/* Actions that are sensitive only when one or more messages are
- * selected: */
-static const GtkActionEntry message_entries[] = {
-    /* Message menu items */
-    {"Reply", BALSA_PIXMAP_REPLY, N_("_Reply..."), MAC_MODIFIER "R",
-     N_("Reply to the current message"), G_CALLBACK(bw_replyto_message_cb)},
-    {"ReplyAll", BALSA_PIXMAP_REPLY_ALL, N_("Reply to _All..."), MAC_MODIFIER "A",
-     N_("Reply to all recipients of the current message"),
-     G_CALLBACK(bw_replytoall_message_cb)},
-    {"ReplyGroup", BALSA_PIXMAP_REPLY_GROUP, N_("Reply to _Group..."), MAC_MODIFIER "G",
-     N_("Reply to mailing list"), G_CALLBACK(bw_replytogroup_message_cb)},
-    {"StoreAddress", BALSA_PIXMAP_BOOK_RED, N_("_Store Address..."), MAC_MODIFIER "S",
-     N_("Store address of sender in addressbook"),
-     G_CALLBACK(bw_store_address_cb)},
-    {"ViewSource", BALSA_PIXMAP_BOOK_OPEN, N_("_View Source..."),
-     "<control>U", N_("View source form of the message"),
-     G_CALLBACK(bw_view_msg_source_cb)},
-    /* All three "Forward" actions and the "Pipe" action have the same
-     * stock_id; the first in this list defines the action tied to the
-     * toolbar's Forward button, so "ForwardDefault" must come before
-     * the others. */
-    {"ForwardDefault", BALSA_PIXMAP_FORWARD, N_("_Forward..."), MAC_MODIFIER "F",
-     N_("Forward the current message"),
-     G_CALLBACK(bw_forward_message_default_cb)},
-#if !defined(ENABLE_TOUCH_UI)
-    {"ForwardAttached", BALSA_PIXMAP_FORWARD, N_("_Forward attached..."), MAC_MODIFIER "F",
-     N_("Forward the current message as attachment"),
-     G_CALLBACK(bw_forward_message_attached_cb)},
-    {"ForwardInline", BALSA_PIXMAP_FORWARD, N_("Forward _inline..."), NULL,
-     N_("Forward the current message inline"),
-     G_CALLBACK(bw_forward_message_inline_cb)},
-    {"Pipe", BALSA_PIXMAP_FORWARD, N_("_Pipe through..."), NULL,
-     N_("Pipe the message through another program"),
-     G_CALLBACK(bw_pipe_message_cb)},
-    {"SelectThread", NULL, N_("Select _Thread"), NULL,
-     N_("Select all messages in current thread"),
-     G_CALLBACK(bw_select_thread_cb)},
-#endif /* ENABLE_TOUCH_UI */
-};
-
-/* Actions that are sensitive only when some message is current: */
-static const GtkActionEntry current_message_entries[] = {
-    /* File menu item */
-    {"Print", "document-print", N_("_Print..."), "<control>P",
-     N_("Print current message"), G_CALLBACK(bw_message_print_cb)},
-    {"SavePart", "document-save", N_("Save Current Part..."), "<control>S",
-     N_("Save currently displayed part of message"),
-     G_CALLBACK(bw_save_current_part_cb)},
-#if !defined(ENABLE_TOUCH_UI)
-    {"NextPart", BALSA_PIXMAP_NEXT_PART, N_("_Next Part"), "<control>period",
-     N_("Next part in message"), G_CALLBACK(bw_next_part_cb)},
-    {"PreviousPart", BALSA_PIXMAP_PREVIOUS_PART, N_("_Previous Part"),
-     "<control>comma", N_("Previous part in message"),
-     G_CALLBACK(bw_previous_part_cb)},
-    {"CopyMessage", "edit-copy", N_("_Copy"), "<control>C",
-     N_("Copy message"), G_CALLBACK(bw_message_copy_cb)},
-    {"SelectText", NULL, N_("_Select Text"), NULL,
-     N_("Select entire mail"), G_CALLBACK(bw_message_select_all_cb)},
-    {"FindInMessage", NULL, N_("Find in _Message"), MAC_MODIFIER "slash",
-     N_("Find a string in this message"),
-     G_CALLBACK(bw_find_in_message_cb)}
-#endif /* ENABLE_TOUCH_UI */
-};
-
-/* Actions that are sensitive only when a message is selected and
- * can be modified: */
-static const GtkActionEntry modify_message_entries[] = {
-    /* Message menu items */
-#if !defined(ENABLE_TOUCH_UI)
-    {"MoveToTrash", "edit-delete", N_("_Move to Trash"), MAC_MODIFIER "D",
-     N_("Move the current message to Trash mailbox"),
-     G_CALLBACK(bw_trash_message_cb)},
-#else  /* ENABLE_TOUCH_UI */
-    {"MoveToTrash", "edit-delete", N_("_Delete to Trash"), MAC_MODIFIER "D",
-     N_("Move the current message to Trash mailbox"),
-     G_CALLBACK(bw_trash_message_cb)},
-    {"ToolbarToggleNew", BALSA_PIXMAP_MARKED_NEW, N_("_New"), NULL,
-     N_("Toggle New"), G_CALLBACK(bw_toggle_new_message_cb)},
-#endif /* ENABLE_TOUCH_UI */
-    {"MessageToggleFlagMenu", NULL, N_("_Toggle Flag")},
-    /* Message:toggle-flag submenu items */
-    {"ToggleFlagged", BALSA_PIXMAP_INFO_FLAGGED, N_("_Flagged"), MAC_MODIFIER "X",
-     N_("Toggle flagged"), G_CALLBACK(bw_toggle_flagged_message_cb)},
-    {"ToggleDeleted", "edit-delete", N_("_Deleted"), "<control>D",
-     N_("Toggle deleted flag"), G_CALLBACK(bw_toggle_deleted_message_cb)},
-    {"ToggleNew", BALSA_PIXMAP_INFO_NEW, N_("_New"), "<control>R",
-     N_("Toggle New"), G_CALLBACK(bw_toggle_new_message_cb)},
-    {"ToggleAnswered", BALSA_PIXMAP_INFO_REPLIED, N_("_Answered"), NULL,
-     N_("Toggle Answered"), G_CALLBACK(bw_toggle_answered_message_cb)},
-};
-
-/* Toggle items */
-static const GtkToggleActionEntry toggle_entries[] = {
-    /* View menu items */
-#if !defined(ENABLE_TOUCH_UI)
-    {"ShowMailboxTree", NULL, N_("_Show Mailbox Tree"), "F9",
-     N_("Toggle display of mailbox and folder tree"),
-     G_CALLBACK(bw_show_mbtree_cb), FALSE},
-    {"ShowMailboxTabs", NULL, N_("Show Mailbox _Tabs"), NULL,
-     N_("Toggle display of mailbox notebook tabs"),
-     G_CALLBACK(bw_show_mbtabs_cb), FALSE},
-    {"ShowToolbar", NULL, N_("Show Too_lbar"), NULL,
-     NULL, G_CALLBACK(bw_show_toolbar_cb), TRUE},
-    {"ShowStatusbar", NULL, N_("Show St_atus Bar"), NULL,
-     NULL, G_CALLBACK(bw_show_statusbar_cb), TRUE},
-    {"ShowSOSbar", NULL, N_("Show _Index Filter"), NULL,
-     NULL, G_CALLBACK(bw_show_sos_bar_cb), TRUE},
-#else  /* ENABLE_TOUCH_UI */
-    {"SortDescending", NULL, N_("_Descending"), NULL,
-     N_("Sort in a descending order"),
-     G_CALLBACK(bw_toggle_order_cb), FALSE},
-    {"ViewFilter", NULL, N_("_View filter"), NULL,
-     N_("Enable quick message index filter"),
-     G_CALLBACK(bw_enable_view_filter_cb), FALSE},
-#endif /* ENABLE_TOUCH_UI */
-    {"Wrap", NULL, N_("_Wrap"), NULL, N_("Wrap message lines"),
-     G_CALLBACK(bw_wrap_message_cb), FALSE},
-    /* Hide messages menu items */
-    {"HideDeleted", NULL, N_("_Deleted"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideUndeleted", NULL, N_("Un_Deleted"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideRead", NULL, N_("_Read"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideUnread", NULL, N_("Un_read"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideFlagged", NULL, N_("_Flagged"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideUnflagged", NULL, N_("Un_flagged"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideAnswered", NULL, N_("_Answered"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    {"HideUnanswered", NULL, N_("Un_answered"), NULL, NULL,
-     G_CALLBACK(bw_hide_changed_cb), FALSE},
-    /* Toolbar items not on any menu */
-    {"ShowAllHeaders", BALSA_PIXMAP_SHOW_HEADERS, N_("All\nheaders"),
-     NULL, N_("Show all headers"),
-     G_CALLBACK(bw_show_all_headers_tool_cb), FALSE},
-    {"ShowPreviewPane", BALSA_PIXMAP_SHOW_PREVIEW, N_("Msg Preview"),
-     NULL, N_("Show preview pane"), G_CALLBACK(bw_show_preview_pane_cb),
-     FALSE}
-};
-
-/* Radio items */
-static const GtkRadioActionEntry shown_hdrs_radio_entries[] = {
-    {"NoHeaders", NULL, N_("_No Headers"), NULL,
-     N_("Display no headers"), HEADERS_NONE},
-    {"SelectedHeaders", NULL, N_("S_elected Headers"), NULL,
-     N_("Display selected headers"), HEADERS_SELECTED},
-    {"AllHeaders", NULL, N_("All _Headers"), NULL,
-     N_("Display all headers"), HEADERS_ALL}
-};
-#if !defined(ENABLE_TOUCH_UI)
-static const GtkRadioActionEntry threading_radio_entries[] = {
-    {"FlatIndex", NULL, N_("_Flat index"), NULL,
-     N_("No threading at all"), LB_MAILBOX_THREADING_FLAT},
-    {"SimpleThreading", NULL, N_("Si_mple threading"), NULL,
-     N_("Simple threading algorithm"), LB_MAILBOX_THREADING_SIMPLE},
-    {"JWZThreading", NULL, N_("_JWZ threading"), NULL,
-     N_("Elaborate JWZ threading"), LB_MAILBOX_THREADING_JWZ}
-};
-#endif /* ENABLE_TOUCH_UI */
-#if defined(ENABLE_TOUCH_UI)
-static const GtkRadioActionEntry sort_radio_entries[] = {
-    {"ByArrival", NULL, N_("By _Arrival"), NULL,
-     N_("Arrival order"), LB_MAILBOX_SORT_NO},
-    {"BySender", NULL, N_("By _Sender"), NULL,
-     N_("Sender order"), LB_MAILBOX_SORT_SENDER},
-    {"BySubject", NULL, N_("By S_ubject"), NULL,
-     N_("Subject order"), LB_MAILBOX_SORT_SUBJECT},
-    {"BySize", NULL, N_("By Si_ze"), NULL,
-     N_("By message size"), LB_MAILBOX_SORT_SIZE},
-    {"Threaded", NULL, N_("_Threaded"), NULL,
-     N_("Use message threading"), LB_MAILBOX_SORT_THREAD}
-};
-#endif /* ENABLE_TOUCH_UI */
-
-static const char *ui_description =
-#if !defined(ENABLE_TOUCH_UI)
-"<ui>"
-"  <menubar name='MainMenu'>"
-"    <menu action='FileMenu'>"
-"      <menu action='FileNewMenu'>"
-"        <menuitem action='NewMessage'/>"
-"        <separator/>"
-"        <menuitem action='NewMbox'/>"
-"        <menuitem action='NewMaildir'/>"
-"        <menuitem action='NewMH'/>"
-"        <menuitem action='NewIMAPBox'/>"
-"        <separator/>"
-"        <menuitem action='NewIMAPFolder'/>"
-"        <menuitem action='NewIMAPSubfolder'/>"
-"      </menu>"
-"      <menuitem action='Continue'/>"
-"      <separator/>"
-"      <menuitem action='GetNewMail'/>"
-"      <menuitem action='SendQueuedMail'/>"
-"      <menuitem action='SendAndReceiveMail'/>"
-"      <separator/>"
-"      <menuitem action='PageSetup'/>"
-"      <menuitem action='Print'/>"
-"      <separator/>"
-"      <menuitem action='AddressBook'/>"
-"      <menu action='MailboxTabMenu'>"
-"        <menuitem action='MailboxTab1'/>"
-"        <menuitem action='MailboxTab2'/>"
-"        <menuitem action='MailboxTab3'/>"
-"        <menuitem action='MailboxTab4'/>"
-"        <menuitem action='MailboxTab5'/>"
-"        <menuitem action='MailboxTab6'/>"
-"        <menuitem action='MailboxTab7'/>"
-"        <menuitem action='MailboxTab8'/>"
-"        <menuitem action='MailboxTab9'/>"
-"        <menuitem action='MailboxTab0'/>"
-"      </menu>"
-"      <separator/>"
-"      <menuitem action='Quit'/>"
-"    </menu>"
-"    <menu action='EditMenu'>"
-"      <menuitem action='Copy'/>"
-"      <menuitem action='SelectAll'/>"
-"      <menuitem action='SelectThread'/>"
-"      <separator/>"
-"      <menuitem action='Find'/>"
-"      <menuitem action='FindNext'/>"
-"      <menuitem action='FindInMessage'/>"
-"      <separator/>"
-"      <menuitem action='Filters'/>"
-"      <menuitem action='ExportFilters'/>"
-"      <separator/>"
-"      <menuitem action='Preferences'/>"
-"    </menu>"
-"    <menu action='ViewMenu'>"
-"      <menuitem action='ShowMailboxTree'/>"
-"      <menuitem action='ShowMailboxTabs'/>"
-"      <menuitem action='ShowToolbar'/>"
-"      <menuitem action='ShowStatusbar'/>"
-"      <menuitem action='ShowSOSbar'/>"
-"      <separator/>"
-"      <menuitem action='Wrap'/>"
-"      <separator/>"
-"      <menuitem action='NoHeaders'/>"
-"      <menuitem action='SelectedHeaders'/>"
-"      <menuitem action='AllHeaders'/>"
-"      <separator/>"
-"      <menuitem action='FlatIndex'/>"
-"      <menuitem action='SimpleThreading'/>"
-"      <menuitem action='JWZThreading'/>"
-"      <separator/>"
-"      <menuitem action='ExpandAll'/>"
-"      <menuitem action='CollapseAll'/>"
-#ifdef HAVE_HTML_WIDGET
-"      <separator/>"
-"      <menuitem action='ZoomIn'/>"
-"      <menuitem action='ZoomOut'/>"
-"      <menuitem action='Zoom100'/>"
-#endif                         /* HAVE_HTML_WIDGET */
-"    </menu>"
-"    <menu action='MailboxMenu'>"
-"      <menuitem action='NextMessage'/>"
-"      <menuitem action='PreviousMessage'/>"
-"      <menuitem action='NextUnread'/>"
-"      <menuitem action='NextFlagged'/>"
-"      <separator/>"
-"      <menu action='MailboxHideMenu'>"
-"        <menuitem action='HideDeleted'/>"
-"        <menuitem action='HideUndeleted'/>"
-"        <menuitem action='HideRead'/>"
-"        <menuitem action='HideUnread'/>"
-"        <menuitem action='HideFlagged'/>"
-"        <menuitem action='HideUnflagged'/>"
-"        <menuitem action='HideAnswered'/>"
-"        <menuitem action='HideUnanswered'/>"
-"      </menu>"
-"      <menuitem action='ResetFilter'/>"
-"      <separator/>"
-"      <menuitem action='MailboxSelectAll'/>"
-"      <separator/>"
-"      <menuitem action='MailboxEdit'/>"
-"      <menuitem action='MailboxDelete'/>"
-"      <separator/>"
-"      <menuitem action='Expunge'/>"
-"      <menuitem action='Close'/>"
-"      <separator/>"
-"      <menuitem action='EmptyTrash'/>"
-"      <separator/>"
-"      <menuitem action='SelectFilters'/>"
-"      <separator/>"
-"      <menuitem action='RemoveDuplicates'/>"
-"    </menu>"
-"    <menu action='MessageMenu'>"
-"      <menuitem action='Reply'/>"
-"      <menuitem action='ReplyAll'/>"
-"      <menuitem action='ReplyGroup'/>"
-"      <menuitem action='ForwardAttached'/>"
-"      <menuitem action='ForwardInline'/>"
-"      <separator/>"
-"      <menuitem action='Pipe'/>"
-"      <separator/>"
-"      <menuitem action='NextPart'/>"
-"      <menuitem action='PreviousPart'/>"
-"      <menuitem action='SavePart'/>"
-"      <menuitem action='ViewSource'/>"
-"      <separator/>"
-"      <menuitem action='CopyMessage'/>"
-"      <menuitem action='SelectText'/>"
-"      <separator/>"
-"      <menuitem action='MoveToTrash'/>"
-"      <menu action='MessageToggleFlagMenu'>"
-"        <menuitem action='ToggleFlagged'/>"
-"        <menuitem action='ToggleDeleted'/>"
-"        <menuitem action='ToggleNew'/>"
-"        <menuitem action='ToggleAnswered'/>"
-"      </menu>"
-"      <separator/>"
-"      <menuitem action='StoreAddress'/>"
-"    </menu>"
-"    <menu action='SettingsMenu'>"
-"      <menuitem action='Toolbars'/>"
-"      <menuitem action='Identities'/>"
-"    </menu>"
-"    <menu action='HelpMenu'>"
-"      <menuitem action='TableOfContents'/>"
-"      <menuitem action='About'/>"
-"    </menu>"
-"  </menubar>"
-"  <toolbar name='Toolbar'>"
-"  </toolbar>"
-"</ui>";
-#else  /* ENABLE_TOUCH_UI */
-"<ui>"
-"  <menubar name='MainMenu'>"
-"    <menu action='FileMenu'>"
-"      <menuitem action='SendAndReceiveMail'/>"
-"      <menuitem action='SendQueuedMail'/>"
-"      <menuitem action='GetNewMail'/>"
-"      <separator/>"
-"      <menu action='MailboxesMenu'>"
-"        <menuitem action='NewMbox'/>"
-"        <menuitem action='NewMaildir'/>"
-"        <menuitem action='NewMH'/>"
-"        <menuitem action='NewIMAPBox'/>"
-"        <separator/>"
-"        <menuitem action='NewIMAPFolder'/>"
-"        <menuitem action='NewIMAPSubfolder'/>"
-"        <separator/>"
-"        <menuitem action='MailboxDelete'/>"
-"        <menuitem action='MailboxEdit'/>"
-"        <separator/>"
-"      </menu>"
-"      <menuitem action='PageSetup'/>"
-"      <menuitem action='Print'/>"
-"      <separator/>"
-"      <menuitem action='Quit'/>"
-"    </menu>"
-"    <menu action='EditMenu'>"
-"      <menuitem action='Copy'/>"
-"      <menuitem action='SelectAll'/>"
-"      <separator/>"
-"      <menuitem action='Find'/>"
-"      <menuitem action='FindNext'/>"
-"    </menu>"
-"    <menu action='ViewMenu'>"
-"      <menuitem action='NextUnread'/>"
-"      <menuitem action='NextMessage'/>"
-"      <menuitem action='PreviousMessage'/>"
-#ifdef HAVE_HTML_WIDGET
-"      <separator/>"
-"      <menuitem action='ZoomIn'/>"
-"      <menuitem action='ZoomOut'/>"
-"      <menuitem action='Zoom100'/>"
-#endif                         /* HAVE_HTML_WIDGET */
-"      <separator/>"
-"      <menu action='ViewMoreMenu'>"
-"        <menuitem action='NextFlagged'/>"
-"        <separator/>"
-"        <menu action='ShownHeadersMenu'>"
-"          <menuitem action='NoHeaders'/>"
-"          <menuitem action='SelectedHeaders'/>"
-"          <menuitem action='AllHeaders'/>"
-"        </menu>"
-"        <menuitem action='Wrap'/>"
-"        <menu action='SortMenu'>"
-"          <menuitem action='SortDescending'/>"
-"          <separator/>"
-"          <menuitem action='ByArrival'/>"
-"          <menuitem action='BySender'/>"
-"          <menuitem action='BySubject'/>"
-"          <menuitem action='BySize'/>"
-"          <menuitem action='Threaded'/>"
-"        </menu>"
-"        <menu action='HideMessagesMenu'>"
-"          <menuitem action='HideDeleted'/>"
-"          <menuitem action='HideUndeleted'/>"
-"          <menuitem action='HideRead'/>"
-"          <menuitem action='HideUnread'/>"
-"          <menuitem action='HideFlagged'/>"
-"          <menuitem action='HideUnflagged'/>"
-"          <menuitem action='HideAnswered'/>"
-"          <menuitem action='HideUnanswered'/>"
-"        </menu>"
-"        <separator/>"
-"        <menuitem action='ExpandAll'/>"
-"        <menuitem action='CollapseAll'/>"
-"        <separator/>"
-"        <menuitem action='ViewFilter'/>"
-"      </menu>"
-"    </menu>"
-"    <menu action='MessageMenu'>"
-"      <menuitem action='NewMessage'/>"
-"      <menuitem action='Reply'/>"
-"      <menuitem action='ReplyAll'/>"
-"      <menuitem action='ForwardDefault'/>"
-"      <separator/>"
-"      <menuitem action='SavePart'/>"
-"      <menuitem action='MoveToTrash'/>"
-"      <separator/>"
-"      <menu action='MessageMoreMenu'>"
-"        <menuitem action='ViewSource'/>"
-"        <menu action='MessageToggleFlagMenu'>"
-"          <menuitem action='ToggleFlagged'/>"
-"          <menuitem action='ToggleDeleted'/>"
-"          <menuitem action='ToggleNew'/>"
-"          <menuitem action='ToggleAnswered'/>"
-"        </menu>"
-"        <menuitem action='StoreAddress'/>"
-"      </menu>"
-"    </menu>"
-"    <menu action='ToolsMenu'>"
-"      <menuitem action='AddressBook'/>"
-"      <menuitem action='EmptyTrash'/>"
-"      <menu action='ToolsFiltersMenu'>"
-"        <menuitem action='ManageFilters'/>"
-"        <menuitem action='ExportFilters'/>"
-"      </menu>"
-"      <menuitem action='Identities'/>"
-"      <menuitem action='Preferences'/>"
-"    </menu>"
-"    <menu action='HelpMenu'>"
-"      <menuitem action='TableOfContents'/>"
-"      <menuitem action='About'/>"
-"    </menu>"
-"  </menubar>"
-"  <toolbar name='Toolbar'>"
-"  </toolbar>"
-"</ui>";
-#endif /* ENABLE_TOUCH_UI */
-
-G_DEFINE_TYPE (BalsaWindow, balsa_window, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE (BalsaWindow, balsa_window, GTK_TYPE_APPLICATION_WINDOW)
 
 static guint window_signals[LAST_SIGNAL] = { 0 };
 
@@ -1361,102 +607,10 @@ bw_set_panes(BalsaWindow * window)
         balsa_index_set_width_preference(BALSA_INDEX(bindex), width_preference);
 }
 
-/*
- * GtkAction helpers
- */
-
-/* Find a GtkAction by name.
- */
-static GtkAction *
-bw_get_action(BalsaWindow * window, const gchar * action_name)
-{
-    GtkAction *action;
-
-    if ((action =
-         gtk_action_group_get_action(window->action_group, action_name)))
-        return action;
-
-    if ((action =
-         gtk_action_group_get_action(window->mailbox_action_group,
-                                     action_name)))
-        return action;
-
-    if ((action =
-         gtk_action_group_get_action(window->current_message_action_group,
-                                     action_name)))
-        return action;
-
-    return gtk_action_group_get_action(window->message_action_group,
-                                       action_name);
-}
-
-/* Set the sensitivity of a GtkAction.
- */
-static void
-bw_set_sensitive(BalsaWindow * window, const gchar * action_name,
-                 gboolean sensitive)
-{
-    GtkAction *action = bw_get_action(window, action_name);
-    gtk_action_set_sensitive(action, sensitive);
-}
-
-/* Set the state of a GtkToggleAction; if block == TRUE,
- * block the handling of signals emitted on the action.
- * Note: if action_name is a GtkRadioAction, and we are connected to the
- * "toggled" signal, we must block the first action in the group, since
- * that is the only action in the group that is connected to the signal;
- * as of now (2008-02-14), we do not use the "toggled" signal, as it is
- * not emitted when the user clicks on the currently active member of
- * the group; instead, we connect to the "activate" signal for all
- * members of the group, so the correct action to block is the one in
- * the call.
- */
-static void
-bw_set_active(BalsaWindow * window, const gchar * action_name,
-              gboolean active, gboolean block)
-{
-    GtkAction *action = bw_get_action(window, action_name);
-
-    if (block)
-        g_signal_handlers_block_matched(action, G_SIGNAL_MATCH_DATA, 0,
-                                        (GQuark) 0, NULL, NULL, window);
-    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), active);
-    if (block)
-        g_signal_handlers_unblock_matched(action, G_SIGNAL_MATCH_DATA, 0,
-                                          (GQuark) 0, NULL, NULL, window);
-}
-
-static gboolean
-bw_get_active(BalsaWindow * window, const gchar * action_name)
-{
-    GtkAction *action = bw_get_action(window, action_name);
-    return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
-}
-
-/* Set the visibility of a GtkAction.
- */
-static void
-bw_set_visible(BalsaWindow * window, const gchar * action_name,
-               gboolean visible)
-{
-    GtkAction *action = bw_get_action(window, action_name);
-    gtk_action_set_visible(action, visible);
-}
-
-/*
- * end of GtkAction helpers
- */
-
-static void
-bw_enable_next_unread(BalsaWindow * window, gboolean has_unread_mailbox)
-{
-    bw_set_sensitive(window, "NextUnread", has_unread_mailbox);
-}
-
 /* Create the toolbar model for the main window's toolbar.
  */
 /* Standard buttons; "" means a separator. */
-static const gchar* main_toolbar[] = {
+static const BalsaToolbarEntry main_toolbar[] = {
 #if defined(ENABLE_TOUCH_UI)
     BALSA_PIXMAP_RECEIVE,
     "",
@@ -1470,22 +624,44 @@ static const gchar* main_toolbar[] = {
     BALSA_PIXMAP_NEXT_UNREAD,
     BALSA_PIXMAP_MARKED_NEW
 #else /* defined(ENABLE_TOUCH_UI) */
-    BALSA_PIXMAP_RECEIVE,
-    "",
-    "edit-delete",
-    "",
-    BALSA_PIXMAP_COMPOSE,
-    BALSA_PIXMAP_CONTINUE,
-    BALSA_PIXMAP_REPLY,
-    BALSA_PIXMAP_REPLY_ALL,
-    BALSA_PIXMAP_FORWARD,
-    "",
-    BALSA_PIXMAP_NEXT_UNREAD,
-    "",
-    "document-print"
+    { "get-new-mail",     BALSA_PIXMAP_RECEIVE     },
+    { "", ""                                       },
+    { "move-to-trash",   "edit-delete"             },
+    { "", ""                                       },
+    { "new-message",      BALSA_PIXMAP_COMPOSE     },
+    { "continue",         BALSA_PIXMAP_CONTINUE    },
+    { "reply",            BALSA_PIXMAP_REPLY       },
+    { "reply-all",        BALSA_PIXMAP_REPLY_ALL   },
+    { "forward-attached", BALSA_PIXMAP_FORWARD     },
+    { "", ""                                       },
+    { "next-unread",      BALSA_PIXMAP_NEXT_UNREAD },
+    { "", ""                                       },
+    { "print",           "document-print"          }
 #endif /* defined(ENABLE_TOUCH_UI) */
 };
 
+/* Optional extra buttons */
+static const BalsaToolbarEntry main_toolbar_extras[] = {
+    { "quit",              "application-exit"          },
+    { "reply-to-group",     BALSA_PIXMAP_REPLY_GROUP   },
+    { "previous-message",   BALSA_PIXMAP_PREVIOUS      },
+    { "next-message",       BALSA_PIXMAP_NEXT          },
+    { "next-flagged",       BALSA_PIXMAP_NEXT_FLAGGED  },
+    { "previous-part",      BALSA_PIXMAP_PREVIOUS_PART },
+    { "next-part",          BALSA_PIXMAP_NEXT_PART     },
+    { "send",               BALSA_PIXMAP_SEND          },
+    { "send-and-receive",   BALSA_PIXMAP_SEND_RECEIVE  },
+    { "save-part",         "document-save"             },
+    { "identities",         BALSA_PIXMAP_IDENTITY      },
+    { "mailbox-close",     "window-close"              },
+    { "mailbox-select-all", BALSA_PIXMAP_MARK_ALL      },
+    { "show-all-headers",   BALSA_PIXMAP_SHOW_HEADERS  },
+    { "reset-filter",      "gtk-cancel"                },
+    { "show-preview-pane",  BALSA_PIXMAP_SHOW_PREVIEW  },
+    { "expunge",           "edit-clear"                },
+    { "empty-trash",       "list-remove"               }
+};
+
 BalsaToolbarModel *
 balsa_window_get_toolbar_model(void)
 {
@@ -1497,127 +673,21 @@ balsa_window_get_toolbar_model(void)
         return model;
 
     standard = NULL;
-    for (i = 0; i < ELEMENTS(main_toolbar); i++)
-        standard = g_slist_append(standard, g_strdup(main_toolbar[i]));
+    for (i = 0; i < G_N_ELEMENTS(main_toolbar); i++) {
+        const BalsaToolbarEntry *entry = &main_toolbar[i];
+        standard = g_slist_prepend(standard, g_strdup(entry->action));
+        standard = g_slist_prepend(standard, g_strdup(entry->icon));
+    }
+    standard = g_slist_reverse(standard);
 
     model =
         balsa_toolbar_model_new(BALSA_TOOLBAR_TYPE_MAIN_WINDOW, standard);
-    balsa_toolbar_model_add_actions(model, entries,
-                                    G_N_ELEMENTS(entries));
-    balsa_toolbar_model_add_actions(model, mailbox_entries,
-                                    G_N_ELEMENTS(mailbox_entries));
-    balsa_toolbar_model_add_actions(model, message_entries,
-                                    G_N_ELEMENTS(message_entries));
-    balsa_toolbar_model_add_actions(model, current_message_entries,
-                                    G_N_ELEMENTS(current_message_entries));
-    balsa_toolbar_model_add_actions(model, modify_message_entries,
-                                    G_N_ELEMENTS(modify_message_entries));
-    balsa_toolbar_model_add_toggle_actions(model, toggle_entries,
-                                           G_N_ELEMENTS(toggle_entries));
+    balsa_toolbar_model_add_entries(model, main_toolbar_extras,
+                                    G_N_ELEMENTS(main_toolbar_extras));
 
     return model;
 }
 
-/* Create a GtkUIManager for a main window, with all the actions, but no
- * ui.
- */
-GtkUIManager *
-balsa_window_ui_manager_new(BalsaWindow * window)
-{
-    GtkUIManager *ui_manager;
-    GtkActionGroup *action_group;
-
-    ui_manager = gtk_ui_manager_new();
-
-    action_group = gtk_action_group_new("BalsaWindow");
-    gtk_action_group_set_translation_domain(action_group, NULL);
-    if (window)
-        window->action_group = action_group;
-    gtk_action_group_add_actions(action_group, entries,
-                                 G_N_ELEMENTS(entries), window);
-    gtk_action_group_add_toggle_actions(action_group, toggle_entries,
-                                        G_N_ELEMENTS(toggle_entries),
-                                        window);
-    /* Add the header option actions.
-     * Note: if we provide a callback, it's connected to the "changed"
-     * signal, which is emitted only when the radio list changes state.
-     * We want to respond also to a click on the current option, so we
-     * connect later to the "activate" signal, and pass a NULL callback
-     * here.  */
-    gtk_action_group_add_radio_actions(action_group,
-                                       shown_hdrs_radio_entries,
-                                       G_N_ELEMENTS
-                                       (shown_hdrs_radio_entries), 0,
-                                       NULL, /* no callback */
-                                       NULL);
-
-    gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
-
-    action_group = gtk_action_group_new("BalsaWindowMailbox");
-    gtk_action_group_set_translation_domain(action_group, NULL);
-    if (window)
-        window->mailbox_action_group = action_group;
-    gtk_action_group_add_actions(action_group, mailbox_entries,
-                                 G_N_ELEMENTS(mailbox_entries),
-                                 window);
-#if !defined(ENABLE_TOUCH_UI)
-    /* Add the threading option actions.
-     * Note: if we provide a callback, it's connected to the "changed"
-     * signal, which is emitted only when the radio list changes state.
-     * We want to respond also to a click on the current option, so we
-     * connect later to the "activate" signal, and pass a NULL callback
-     * here.  */
-    gtk_action_group_add_radio_actions(action_group,
-                                       threading_radio_entries,
-                                       G_N_ELEMENTS
-                                       (threading_radio_entries), 0,
-                                       NULL, /* no callback */
-                                       NULL);
-#endif /* ENABLE_TOUCH_UI */
-#if defined(ENABLE_TOUCH_UI)
-    gtk_action_group_add_radio_actions(action_group,
-                                       sort_radio_entries,
-                                       G_N_ELEMENTS
-                                       (sort_radio_entries), 0,
-                                       G_CALLBACK(bw_sort_change_cb),
-                                       window);
-#endif /* ENABLE_TOUCH_UI */
-
-    gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
-
-    action_group = gtk_action_group_new("BalsaWindowMessage");
-    gtk_action_group_set_translation_domain(action_group, NULL);
-    if (window)
-        window->message_action_group = action_group;
-    gtk_action_group_add_actions(action_group, message_entries,
-                                 G_N_ELEMENTS(message_entries),
-                                 window);
-
-    gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
-
-    action_group = gtk_action_group_new("BalsaWindowCurrentMessage");
-    gtk_action_group_set_translation_domain(action_group, NULL);
-    if (window)
-        window->current_message_action_group = action_group;
-    gtk_action_group_add_actions(action_group, current_message_entries,
-                                 G_N_ELEMENTS(current_message_entries),
-                                 window);
-
-    gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
-
-    action_group = gtk_action_group_new("BalsaWindowModifyMessage");
-    gtk_action_group_set_translation_domain(action_group, NULL);
-    if (window)
-        window->modify_message_action_group = action_group;
-    gtk_action_group_add_actions(action_group, modify_message_entries,
-                                 G_N_ELEMENTS(modify_message_entries),
-                                 window);
-
-    gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
-
-    return ui_manager;
-}
-
 /*
  * "window-state-event" signal handler
  *
@@ -1657,33 +727,1432 @@ bw_is_active_notify(GObject * gobject, GParamSpec * pspec,
     }
 }
 
+/*
+ * GMenu stuff
+ */
+
+/*
+ * GAction helpers
+ */
+
+/*
+ * Set and get the state of a toggle action
+ */
+static void
+bw_action_set_boolean(BalsaWindow * window,
+                      const gchar * action_name,
+                      gboolean      state)
+{
+    GAction *action;
+
+    action = g_action_map_lookup_action(G_ACTION_MAP(window), action_name);
+    if (action)
+        g_simple_action_set_state(G_SIMPLE_ACTION(action),
+                                  g_variant_new_boolean(state));
+    else
+        g_print("%s action \"%s\" not found\n", __func__, action_name);
+}
+
+static gboolean
+bw_action_get_boolean(BalsaWindow * window,
+                      const gchar * action_name)
+{
+    GAction *action;
+    gboolean retval = FALSE;
+
+    action = g_action_map_lookup_action(G_ACTION_MAP(window), action_name);
+    if (action) {
+        GVariant *action_state;
+
+        action_state = g_action_get_state(action);
+        retval = g_variant_get_boolean(action_state);
+        g_variant_unref(action_state);
+    } else
+        g_print("%s action \"%s\" not found\n", __func__, action_name);
+
+    return retval;
+}
+
+/*
+ * Set the state of a radio action
+ */
+
+static void
+bw_action_set_string(BalsaWindow * window,
+                     const gchar * action_name,
+                     const gchar * state)
+{
+    GAction *action;
+
+    action = g_action_map_lookup_action(G_ACTION_MAP(window), action_name);
+    if (action)
+        g_simple_action_set_state(G_SIMPLE_ACTION(action),
+                                  g_variant_new_string(state));
+    else
+        g_print("%s action \"%s\" not found\n", __func__, action_name);
+}
+
+/*
+ * Enable or disable an action
+ */
+
+static void
+bw_action_set_enabled(BalsaWindow * window,
+                      const gchar * action_name,
+                      gboolean      enabled)
+{
+    GActionMap *action_map;
+    GAction *action;
+
+    if (g_object_get_data(G_OBJECT(window), "destroying"))
+        return;
+
+    action_map = G_ACTION_MAP(window);
+    action = g_action_map_lookup_action(action_map, action_name);
+    /* FIXME Remove test when all actions are implemented! */
+    if (action)
+        g_simple_action_set_enabled(G_SIMPLE_ACTION(action), enabled);
+    else
+        g_print("%s action \"%s\" not found in menubar\n", __func__,
+                action_name);
+}
+
+static void
+bw_app_action_set_enabled(BalsaWindow * window,
+                          const gchar * action_name,
+                          gboolean      enabled)
+{
+    GActionMap *action_map;
+    GAction *action;
+
+    if (g_object_get_data(G_OBJECT(window), "destroying"))
+        return;
+
+    action_map =
+        G_ACTION_MAP(gtk_window_get_application(GTK_WINDOW(window)));
+    action = g_action_map_lookup_action(action_map, action_name);
+    /* FIXME Remove test when all actions are implemented! */
+    if (action)
+        g_simple_action_set_enabled(G_SIMPLE_ACTION(action), enabled);
+    else
+        g_print("%s action \"%s\" not found in appmenu\n", __func__,
+                action_name);
+}
+
+/*
+ * Enable or disable a group of actions
+ */
+
+static void
+bw_actions_set_enabled(BalsaWindow         * window,
+                       const gchar * const * actions,
+                       guint                 n_actions,
+                       gboolean              enabled)
+{
+    guint i;
+
+    for (i = 0; i < n_actions; i++)
+        bw_action_set_enabled(window, *actions++, enabled);
+}
+
+/*
+ * End of GAction helpers
+ */
+
+/*
+ * Common callback for the "activated" signal of a toggle action
+ */
+
+static void
+toggle_activated(GSimpleAction * action,
+                 GVariant      * parameter,
+                 gpointer        user_data)
+{
+    GVariant *action_state;
+    gboolean state;
+
+    action_state = g_action_get_state(G_ACTION(action));
+    state = g_variant_get_boolean(action_state);
+    g_action_change_state(G_ACTION(action), g_variant_new_boolean(!state));
+    g_variant_unref(action_state);
+}
+
+/*
+ * Common callback for the "activated" signal of a radio action
+ */
+
+static void
+radio_activated(GSimpleAction * action,
+                GVariant      * parameter,
+                gpointer        user_data)
+{
+    g_action_change_state(G_ACTION(action), parameter);
+}
+
+
+/*
+ * Helper for some show/hide actions
+ */
+
+static void
+bw_show_or_hide_widget(GSimpleAction * action,
+                       GVariant      * state,
+                       gboolean      * active,
+                       GtkWidget     * widget)
+{
+    *active = g_variant_get_boolean(state);
+    if (*active)
+        gtk_widget_show(widget);
+    else
+        gtk_widget_hide(widget);
+    g_simple_action_set_state(action, state);
+}
+
+/*
+ * Callbacks for various actions' "activated" signals
+ */
+
+static void
+new_message_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaSendmsg *smwindow;
+
+    smwindow = sendmsg_window_compose();
+
+#if !defined(ENABLE_TOUCH_UI)
+    g_signal_connect(G_OBJECT(smwindow->window), "destroy",
+                     G_CALLBACK(bw_send_msg_window_destroy_cb), user_data);
+#endif /*ENABLE_TOUCH_UI */
+}
+
+static void
+new_mbox_activated(GSimpleAction * action,
+                   GVariant      * parameter,
+                   gpointer        user_data)
+{
+    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_MBOX);
+}
+
+static void
+new_maildir_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_MAILDIR);
+}
+
+static void
+new_mh_activated(GSimpleAction * action,
+                 GVariant      * parameter,
+                 gpointer        user_data)
+{
+    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_MH);
+}
+
+static void
+new_imap_box_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_IMAP);
+}
+
+static void
+new_imap_folder_activated(GSimpleAction * action,
+                          GVariant      * parameter,
+                          gpointer        user_data)
+{
+    folder_conf_imap_node(NULL);
+}
+
+static void
+new_imap_subfolder_activated(GSimpleAction * action,
+                             GVariant      * parameter,
+                             gpointer        user_data)
+{
+    folder_conf_imap_sub_node(NULL);
+}
+
+static void
+address_book_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+    GtkWidget *ab;
+
+    ab = balsa_ab_window_new(FALSE, window);
+    gtk_widget_show(GTK_WIDGET(ab));
+}
+
+static void
+prefs_activated(GSimpleAction * action,
+                GVariant      * parameter,
+                gpointer        user_data)
+{
+    open_preferences_manager(NULL, user_data);
+}
+
+static void
+help_activated(GSimpleAction * action,
+               GVariant      * parameter,
+               gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+    GdkScreen *screen;
+    GError *err = NULL;
+
+    screen = gtk_window_get_screen(window);
+    gtk_show_uri(screen, "help:balsa", gtk_get_current_event_time(),
+                 &err);
+    if (err) {
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("Error displaying help: %s\n"), err->message);
+        g_error_free(err);
+    }
+}
+
+static void
+about_activated(GSimpleAction * action,
+                GVariant      * parameter,
+                gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+    const gchar *authors[] = {
+        "Balsa Maintainers <balsa-maintainer theochem kth se>:",
+        "Peter Bloomfield <PeterBloomfield bellsouth net>",
+       "Bart Visscher <magick linux-fan com>",
+        "Emmanuel Allaud <e allaud wanadoo fr>",
+        "Carlos Morgado <chbm gnome org>",
+        "Pawel Salek <pawsa theochem kth se>",
+        "and many others (see AUTHORS file)",
+        NULL
+    };
+    const gchar *documenters[] = {
+        NULL
+    };
+
+    const gchar *translator_credits = _("translator-credits");
+    /* FIXME: do we need error handling for this? */
+    GdkPixbuf *balsa_logo =
+        gdk_pixbuf_new_from_file(BALSA_DATA_PREFIX
+                                 "/pixmaps/balsa_logo.png", NULL);
+
+    gtk_show_about_dialog(window,
+                          "version", BALSA_VERSION,
+                          "copyright",
+                          "Copyright \xc2\xa9 1997-2013 The Balsa Developers",
+                          "comments",
+                          _("The Balsa email client is part of "
+                            "the GNOME desktop environment."),
+                          "authors", authors,
+                          "documenters", documenters,
+                          /* license ? */
+                          "title", _("About Balsa"),
+                          "translator-credits",
+                          strcmp(translator_credits, "translator-credits") ?
+                         translator_credits : NULL,
+                         "logo", balsa_logo,
+                          "website", "http://balsa.gnome.org";,
+                          "wrap-license", TRUE,
+                          NULL);
+    g_object_unref(balsa_logo);
+}
+
+static void
+quit_activated(GSimpleAction * action,
+               GVariant      * parameter,
+               gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+    GdkEventAny e = { GDK_DELETE, NULL, 0 };
+
+    e.window = gtk_widget_get_window(GTK_WIDGET(window));
+    libbalsa_information_parented(window,
+                                  LIBBALSA_INFORMATION_MESSAGE,
+                                  _("Balsa closes files and connections."
+                                    "Please wait..."));
+    while(gtk_events_pending())
+        gtk_main_iteration_do(FALSE);
+    gdk_event_put((GdkEvent*)&e);
+}
+
+static void
+continue_activated(GSimpleAction * action,
+                   GVariant      * parameter,
+                   gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+
+    if (index
+        && BALSA_INDEX(index)->mailbox_node->mailbox == balsa_app.draftbox)
+        balsa_message_continue(BALSA_INDEX(index));
+    else
+        balsa_mblist_open_mailbox(balsa_app.draftbox);
+}
+
+static void
+get_new_mail_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    check_new_messages_real(window, TYPE_CALLBACK);
+
+    if (balsa_app.check_mail_auto) {
+        /* restart the timer */
+        update_timer(TRUE, balsa_app.check_mail_timer);
+    }
+}
+
+static void
+send_queued_mail_activated(GSimpleAction * action,
+                           GVariant      * parameter,
+                           gpointer        user_data)
+{
+    libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url,
+#if ENABLE_ESMTP
+                           balsa_app.smtp_servers,
+#endif /* ENABLE_ESMTP */
+                          balsa_app.debug);
+}
+
+static void
+send_and_receive_mail_activated(GSimpleAction * action,
+                                GVariant      * parameter,
+                                gpointer        user_data)
+{
+    get_new_mail_activated(action, parameter, user_data);
+    send_queued_mail_activated(action, parameter, user_data);
+}
+
+static void
+page_setup_activated(GSimpleAction * action,
+                     GVariant      * parameter,
+                     gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+
+    message_print_page_setup(window);
+}
+
+static void
+print_activated(GSimpleAction * action,
+                GVariant      * parameter,
+                gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+    BalsaIndex *bindex;
+
+    index = balsa_window_find_current_index(window);
+    if (!index)
+        return;
+
+    bindex = BALSA_INDEX(index);
+    if (bindex->current_msgno) {
+        LibBalsaMessage *message =
+            libbalsa_mailbox_get_message(bindex->mailbox_node->mailbox,
+                                         bindex->current_msgno);
+        if (!message)
+            return;
+        message_print(message, GTK_WINDOW(window));
+        g_object_unref(message);
+    }
+}
+
+static void
+copy_activated(GSimpleAction * action,
+               GVariant      * parameter,
+               gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+    guint signal_id;
+    GtkWidget *focus_widget = gtk_window_get_focus(window);
+
+    if (!focus_widget)
+       return;
+
+    signal_id = g_signal_lookup("copy-clipboard",
+                                G_TYPE_FROM_INSTANCE(focus_widget));
+    if (signal_id)
+        g_signal_emit(focus_widget, signal_id, (GQuark) 0);
+#ifdef HAVE_HTML_WIDGET
+    else if (libbalsa_html_can_select(focus_widget))
+       libbalsa_html_copy(focus_widget);
+#endif /* HAVE_HTML_WIDGET */
+}
+
+static void
+select_all_activated(GSimpleAction * action,
+                     GVariant      * parameter,
+                     gpointer        user_data)
+{
+    GtkWindow *window = GTK_WINDOW(user_data);
+
+    balsa_window_select_all(window);
+}
+
+static void
+select_thread_activated(GSimpleAction * action,
+                        GVariant      * parameter,
+                        gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bindex;
+
+    if ((bindex = balsa_window_find_current_index(window)))
+        balsa_index_select_thread(BALSA_INDEX(bindex));
+}
+
+static void
+find_activated(GSimpleAction * action,
+               GVariant      * parameter,
+               gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bindex;
+
+    if ((bindex = balsa_window_find_current_index(window)))
+        bw_find_real(window, BALSA_INDEX(bindex), FALSE);
+}
+
+static void
+find_next_activated(GSimpleAction * action,
+                    GVariant      * parameter,
+                    gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget * bindex;
+
+    if ((bindex = balsa_window_find_current_index(window)))
+       bw_find_real(window, BALSA_INDEX(bindex), TRUE);
+}
+
+static void
+find_in_message_activated(GSimpleAction * action,
+                          GVariant      * parameter,
+                          gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    if (balsa_app.previewpane)
+        balsa_message_find_in_message(BALSA_MESSAGE(window->preview));
+}
+
+static void
+filters_activated(GSimpleAction * action,
+                  GVariant      * parameter,
+                  gpointer        user_data)
+{
+    filters_edit_dialog();
+}
+
+static void
+export_filters_activated(GSimpleAction * action,
+                         GVariant      * parameter,
+                         gpointer        user_data)
+{
+    filters_export_dialog();
+}
+
+static void
+expand_all_activated(GSimpleAction * action,
+                     GVariant      * parameter,
+                     gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_update_tree(BALSA_INDEX(index), TRUE);
+}
+
+static void
+collapse_all_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_update_tree(BALSA_INDEX(index), FALSE);
+}
+
+#ifdef HAVE_HTML_WIDGET
+static void
+zoom_in_activated(GSimpleAction * action,
+                  GVariant      * parameter,
+                  gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bm = window->preview;
+
+    balsa_message_zoom(BALSA_MESSAGE(bm), 1);
+}
+
+static void
+zoom_out_activated(GSimpleAction * action,
+                   GVariant      * parameter,
+                   gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bm = window->preview;
+
+    balsa_message_zoom(BALSA_MESSAGE(bm), -1);
+}
+
+static void
+zoom_normal_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bm = window->preview;
+
+    balsa_message_zoom(BALSA_MESSAGE(bm), 0);
+}
+#endif                         /* HAVE_HTML_WIDGET */
+
+static void
+next_message_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_select_next(BALSA_INDEX(index));
+}
+
+static void
+previous_message_activated(GSimpleAction * action,
+                           GVariant      * parameter,
+                           gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_select_previous(BALSA_INDEX(index));
+}
+
+static void
+next_unread_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_window_next_unread(window);
+}
+
+static void
+next_flagged_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_select_next_flagged(BALSA_INDEX(index));
+}
+
+static void
+reset_filter_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    /* do it by resetting the sos filder */
+    gtk_entry_set_text(GTK_ENTRY(window->sos_entry), "");
+    index = balsa_window_find_current_index(window);
+    bw_set_view_filter(window, BALSA_INDEX(index)->filter_no,
+                       window->sos_entry);
+}
+
+static void
+mailbox_select_all_activated(GSimpleAction * action,
+                             GVariant      * parameter,
+                             gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    gtk_widget_grab_focus(index);
+    balsa_window_select_all(GTK_WINDOW(window));
+}
+
+static void
+mailbox_edit_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    mailbox_conf_edit_cb(NULL, NULL);
+}
+
+static void
+mailbox_delete_activated(GSimpleAction * action,
+                         GVariant      * parameter,
+                         gpointer        user_data)
+{
+    mailbox_conf_delete_cb(NULL, NULL);
+}
+
+static void
+mailbox_expunge_activated(GSimpleAction * action,
+                          GVariant      * parameter,
+                          gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_expunge(BALSA_INDEX(index));
+}
+
+static void
+mailbox_close_activated(GSimpleAction * action,
+                        GVariant      * parameter,
+                        gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    if (index)
+        balsa_mblist_close_mailbox(BALSA_INDEX(index)->mailbox_node->
+                                   mailbox);
+}
+
+static void
+empty_trash_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    empty_trash(window);
+}
+
+static void
+select_filters_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    if (index)
+        filters_run_dialog(BALSA_INDEX(index)->mailbox_node->mailbox);
+    else
+       /* FIXME : Perhaps should we be able to apply filters on folders (ie recurse on all mailboxes in it),
+          but there are problems of infinite recursion (when one mailbox being filtered is also the 
destination
+          of the filter action (eg a copy)). So let's see that later :) */
+       balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("You can apply filters only on mailbox\n"));
+}
+
+static void
+remove_duplicates_activated(GSimpleAction * action,
+                            GVariant      * parameter,
+                            gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+
+    index = balsa_window_find_current_index(window);
+    if (index) {
+        LibBalsaMailbox *mailbox =
+            BALSA_INDEX(index)->mailbox_node->mailbox;
+        GError *err = NULL;
+        gint dup_count =
+            libbalsa_mailbox_move_duplicates(mailbox, NULL, &err);
+        if (err) {
+            balsa_information(LIBBALSA_INFORMATION_WARNING,
+                              _("Removing duplicates failed: %s"),
+                              err->message);
+            g_error_free(err);
+        } else {
+           if(dup_count)
+                balsa_information(LIBBALSA_INFORMATION_MESSAGE,
+                                  ngettext("Removed %d duplicate",
+                                           "Removed %d duplicates",
+                                           dup_count), dup_count);
+           else
+               balsa_information(LIBBALSA_INFORMATION_MESSAGE,
+                                 _("No duplicates found"));
+       }
+
+    }
+}
+
+static void
+reply_activated(GSimpleAction * action,
+                GVariant      * parameter,
+                gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_reply(balsa_window_find_current_index(window));
+}
+
+static void
+reply_all_activated(GSimpleAction * action,
+                    GVariant      * parameter,
+                    gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_replytoall(balsa_window_find_current_index(window));
+}
+
+static void
+reply_group_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_replytogroup(balsa_window_find_current_index(window));
+}
+
+static void
+forward_attached_activated(GSimpleAction * action,
+                           GVariant      * parameter,
+                           gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_forward_attached(balsa_window_find_current_index(window));
+}
+
+static void
+forward_inline_activated(GSimpleAction * action,
+                         GVariant      * parameter,
+                         gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_forward_inline(balsa_window_find_current_index(window));
+}
+
+static void
+pipe_activated(GSimpleAction * action,
+               GVariant      * parameter,
+               gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_index_pipe(BALSA_INDEX
+                     (balsa_window_find_current_index(window)));
+}
+
+static void
+next_part_activated(GSimpleAction * action,
+                    GVariant      * parameter,
+                    gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_next_part(BALSA_MESSAGE(window->preview));
+}
+
+static void
+previous_part_activated(GSimpleAction * action,
+                        GVariant      * parameter,
+                        gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_previous_part(BALSA_MESSAGE(window->preview));
+}
+
+static void
+save_part_activated(GSimpleAction * action,
+                    GVariant      * parameter,
+                    gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_save_current_part(BALSA_MESSAGE(window->preview));
+}
+
+static void
+view_source_activated(GSimpleAction * action,
+                      GVariant      * parameter,
+                      gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bindex;
+    GList *messages, *list;
+
+    bindex = balsa_window_find_current_index(window);
+    g_return_if_fail(bindex != NULL);
+
+    messages = balsa_index_selected_list(BALSA_INDEX(bindex));
+    for (list = messages; list; list = list->next) {
+       LibBalsaMessage *message = list->data;
+
+       libbalsa_show_message_source(balsa_app.application,
+                                     message, balsa_app.message_font,
+                                    &balsa_app.source_escape_specials,
+                                     &balsa_app.source_width,
+                                     &balsa_app.source_height);
+    }
+
+    g_list_free_full(messages, g_object_unref);
+}
+
+static void
+copy_message_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    if (balsa_message_grab_focus(BALSA_MESSAGE(window->preview)))
+        copy_activated(action, parameter, user_data);
+}
+
+static void
+select_text_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    if (balsa_message_grab_focus(BALSA_MESSAGE(window->preview)))
+       balsa_window_select_all(user_data);
+}
+
+static void
+move_to_trash_activated(GSimpleAction * action,
+                       GVariant      * parameter,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_message_move_to_trash(balsa_window_find_current_index(window));
+}
+
+/*
+ * Helper for toggling flags
+ */
+static void
+toggle_flag(LibBalsaMessageFlag flag, gpointer user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *bindex;
+
+    bindex = balsa_window_find_current_index(window);
+    balsa_index_toggle_flag(BALSA_INDEX(bindex), flag);
+}
+
+static void
+toggle_flagged_activated(GSimpleAction * action,
+                         GVariant      * parameter,
+                         gpointer        user_data)
+{
+    toggle_flag(LIBBALSA_MESSAGE_FLAG_FLAGGED, user_data);
+}
+
+static void
+toggle_deleted_activated(GSimpleAction * action,
+                         GVariant      * parameter,
+                         gpointer        user_data)
+{
+    toggle_flag(LIBBALSA_MESSAGE_FLAG_DELETED, user_data);
+}
+
+static void
+toggle_new_activated(GSimpleAction * action,
+                     GVariant      * parameter,
+                     gpointer        user_data)
+{
+    toggle_flag(LIBBALSA_MESSAGE_FLAG_NEW, user_data);
+}
+
+static void
+toggle_answered_activated(GSimpleAction * action,
+                          GVariant      * parameter,
+                          gpointer        user_data)
+{
+    toggle_flag(LIBBALSA_MESSAGE_FLAG_REPLIED, user_data);
+}
+
+static void
+store_address_activated(GSimpleAction * action,
+                          GVariant      * parameter,
+                          gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index = balsa_window_find_current_index(window);
+    GList *messages;
+
+    g_assert(index != NULL);
+
+    messages = balsa_index_selected_list(BALSA_INDEX(index));
+    balsa_store_address_from_messages(messages);
+    g_list_free_full(messages, g_object_unref);
+}
+
+/*
+ * Callbacks for various toggle actions' "change-state" signals
+ */
+
+static void
+show_mailbox_tree_change_state(GSimpleAction * action,
+                               GVariant      * state,
+                               gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_app.show_mblist = g_variant_get_boolean(state);
+    bw_show_mbtree(window);
+    g_simple_action_set_state(action, state);
+}
+
+static void
+show_mailbox_tabs_change_state(GSimpleAction * action,
+                               GVariant      * state,
+                               gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_app.show_notebook_tabs = g_variant_get_boolean(state);
+    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(window->notebook),
+                               balsa_app.show_notebook_tabs);
+    g_simple_action_set_state(action, state);
+}
+
+static void
+show_toolbar_change_state(GSimpleAction * action,
+                          GVariant      * state,
+                          gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    bw_show_or_hide_widget(action, state, &balsa_app.show_main_toolbar,
+                           window->toolbar);
+}
+
+static void
+show_statusbar_change_state(GSimpleAction * action,
+                            GVariant      * state,
+                            gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    bw_show_or_hide_widget(action, state, &balsa_app.show_statusbar,
+                           window->bottom_bar);
+}
+
+static void
+show_sos_bar_change_state(GSimpleAction * action,
+                          GVariant      * state,
+                          gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    bw_show_or_hide_widget(action, state, &balsa_app.show_sos_bar,
+                           window->sos_bar);
+}
+
+static void
+wrap_change_state(GSimpleAction * action,
+                  GVariant      * state,
+                  gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    balsa_app.browse_wrap = g_variant_get_boolean(state);
+
+    balsa_message_set_wrap(BALSA_MESSAGE(window->preview),
+                           balsa_app.browse_wrap);
+    refresh_preferences_manager();
+
+    g_simple_action_set_state(action, state);
+}
+
+/* Really, entire mailbox_hide_menu should be build dynamically from
+ * the hide_states array since different mailboxes support different
+ * set of flags/keywords. */
+static const struct {
+    LibBalsaMessageFlag flag;
+    unsigned set:1;
+    gint states_index;
+    const gchar *g_action_name;
+} hide_states[] = {
+    { LIBBALSA_MESSAGE_FLAG_DELETED, 1, 0, "hide-deleted"   },
+    { LIBBALSA_MESSAGE_FLAG_DELETED, 0, 1, "hide-undeleted" },
+    { LIBBALSA_MESSAGE_FLAG_NEW,     0, 2, "hide-read"      },
+    { LIBBALSA_MESSAGE_FLAG_NEW,     1, 3, "hide-unread"    },
+    { LIBBALSA_MESSAGE_FLAG_FLAGGED, 1, 4, "hide-flagged"   },
+    { LIBBALSA_MESSAGE_FLAG_FLAGGED, 0, 5, "hide-unflagged" },
+    { LIBBALSA_MESSAGE_FLAG_REPLIED, 1, 6, "hide-answered"  },
+    { LIBBALSA_MESSAGE_FLAG_REPLIED, 0, 7, "hide-unanswered" }
+};
+
+static void bw_hide_changed_set_view_filter(BalsaWindow * window);
+
+static void
+hide_change_state(GSimpleAction * action,
+                  GVariant      * state,
+                  gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+
+    /* PART 1: assure menu consistency */
+    if (g_variant_get_boolean(state)) {
+        /* we may need to deactivate coupled negated flag. */
+        const gchar *action_name = g_action_get_name(G_ACTION(action));
+        unsigned curr_idx, i;
+
+        for (i = 0; i < G_N_ELEMENTS(hide_states); i++)
+            if (strcmp(action_name, hide_states[i].g_action_name) == 0)
+                break;
+        g_assert(i < G_N_ELEMENTS(hide_states));
+        curr_idx = hide_states[i].states_index;
+
+        for (i = 0; i < G_N_ELEMENTS(hide_states); i++) {
+            int states_idx = hide_states[i].states_index;
+
+            if (!bw_action_get_boolean(window,
+                                       hide_states[i].g_action_name))
+                continue;
+
+            if (hide_states[states_idx].flag == hide_states[curr_idx].flag
+                && hide_states[states_idx].set !=
+                hide_states[curr_idx].set) {
+                bw_action_set_boolean(window, hide_states[i].g_action_name,
+                                      FALSE);
+            }
+        }
+    }
+
+    g_simple_action_set_state(action, state);
+
+    /* PART 2: do the job. */
+    bw_hide_changed_set_view_filter(window);
+}
+
+/*
+ * Callbacks for various radio actions' "change-state" signals
+ */
+static void
+bw_reset_show_all_headers(BalsaWindow * window)
+{
+    if (balsa_app.show_all_headers) {
+        bw_action_set_boolean(window, "show-all-headers", FALSE);
+        balsa_app.show_all_headers = FALSE;
+    }
+}
+
+static void
+header_change_state(GSimpleAction * action,
+                    GVariant      * state,
+                    gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    const gchar *value;
+    ShownHeaders sh;
+
+    value = g_variant_get_string(state, NULL);
+
+    if (strcmp(value, "none") == 0)
+        sh = HEADERS_NONE;
+    else if (strcmp(value, "selected") == 0)
+        sh = HEADERS_SELECTED;
+    else if (strcmp(value, "all") == 0)
+        sh = HEADERS_ALL;
+    else {
+        g_print("%s unknown value \"%s\"\n", __func__, value);
+        return;
+    }
+
+    balsa_app.shown_headers = sh;
+    bw_reset_show_all_headers(window);
+    balsa_message_set_displayed_headers(BALSA_MESSAGE(window->preview),
+                                        sh);
+
+    g_simple_action_set_state(action, state);
+}
+
+static void
+threading_change_state(GSimpleAction * action,
+                       GVariant      * state,
+                       gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    GtkWidget *index;
+    const gchar *value;
+    LibBalsaMailboxThreadingType type;
+    BalsaMailboxNode *mbnode;
+    LibBalsaMailbox *mailbox;
+
+    value = g_variant_get_string(state, NULL);
+
+    if (strcmp(value, "flat") == 0)
+        type = LB_MAILBOX_THREADING_FLAT;
+    else if (strcmp(value, "simple") == 0)
+        type = LB_MAILBOX_THREADING_SIMPLE;
+    else if (strcmp(value, "jwz") == 0)
+        type = LB_MAILBOX_THREADING_JWZ;
+    else {
+        g_print("%s unknown value \"%s\"\n", __func__, value);
+        return;
+    }
+
+    index = balsa_window_find_current_index(window);
+    balsa_index_set_threading_type(BALSA_INDEX(index), type);
+
+    /* bw->current_index may have been destroyed and cleared during
+     * set-threading: */
+    index = balsa_window_find_current_index(window);
+    if (index && (mbnode = BALSA_INDEX(index)->mailbox_node)
+        && (mailbox = mbnode->mailbox))
+        bw_enable_expand_collapse(window, mailbox);
+
+    g_simple_action_set_state(action, state);
+}
+
+/*
+ * End of callbacks
+ */
+
+static void
+bw_set_menus(BalsaWindow * window)
+{
+    static GActionEntry app_entries[] = {
+        {"new-message",           new_message_activated},
+        {"new-mbox",              new_mbox_activated},
+        {"new-maildir",           new_maildir_activated},
+        {"new-mh",                new_mh_activated},
+        {"new-imap-box",          new_imap_box_activated},
+        {"new-imap-folder",       new_imap_folder_activated},
+        {"new-imap-subfolder",    new_imap_subfolder_activated},
+        {"address-book",          address_book_activated},
+        {"prefs",                 prefs_activated},
+        {"help",                  help_activated},
+        {"about",                 about_activated},
+        {"quit",                  quit_activated}
+    };
+    static GActionEntry win_entries[] = {
+        {"continue",              continue_activated},
+        {"get-new-mail",          get_new_mail_activated},
+        {"send-queued-mail",      send_queued_mail_activated},
+        {"send-and-receive-mail", send_and_receive_mail_activated},
+        {"page-setup",            page_setup_activated},
+        {"print",                 print_activated},
+        {"copy",                  copy_activated},
+        {"select-all",            select_all_activated},
+        {"select-thread",         select_thread_activated},
+        {"find",                  find_activated},
+        {"find-next",             find_next_activated},
+        {"find-in-message",       find_in_message_activated},
+        {"filters",               filters_activated},
+        {"export-filters",        export_filters_activated},
+        {"show-mailbox-tree",     toggle_activated, NULL, "false",
+                                  show_mailbox_tree_change_state},
+        {"show-mailbox-tabs",     toggle_activated, NULL, "false",
+                                  show_mailbox_tabs_change_state},
+        {"show-toolbar",          toggle_activated, NULL, "false",
+                                  show_toolbar_change_state},
+        {"show-statusbar",        toggle_activated, NULL, "false",
+                                  show_statusbar_change_state},
+        {"show-sos-bar",          toggle_activated, NULL, "false",
+                                  show_sos_bar_change_state},
+        {"wrap",                  toggle_activated, NULL, "false",
+                                  wrap_change_state},
+        {"headers",               radio_activated, "s", "'none'",
+                                  header_change_state},
+        {"threading",             radio_activated, "s", "'flat'",
+                                  threading_change_state},
+        {"expand-all",            expand_all_activated},
+        {"collapse-all",          collapse_all_activated},
+#ifdef HAVE_HTML_WIDGET
+        {"zoom-in",               zoom_in_activated},
+        {"zoom-out",              zoom_out_activated},
+        {"zoom-normal",           zoom_normal_activated},
+#endif                         /* HAVE_HTML_WIDGET */
+        {"next-message",          next_message_activated},
+        {"previous-message",      previous_message_activated},
+        {"next-unread",           next_unread_activated},
+        {"next-flagged",          next_flagged_activated},
+        {"hide-deleted",          toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-undeleted",        toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-read",             toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-unread",           toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-flagged",          toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-unflagged",        toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-answered",         toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"hide-unanswered",       toggle_activated, NULL, "false",
+                                  hide_change_state},
+        {"reset-filter",          reset_filter_activated},
+        {"mailbox-select-all",    mailbox_select_all_activated},
+        {"mailbox-edit",          mailbox_edit_activated},
+        {"mailbox-delete",        mailbox_delete_activated},
+        {"mailbox-expunge",       mailbox_expunge_activated},
+        {"mailbox-close",         mailbox_close_activated},
+        {"empty-trash",           empty_trash_activated},
+        {"select-filters",        select_filters_activated},
+        {"remove-duplicates",     remove_duplicates_activated},
+        {"reply",                 reply_activated},
+        {"reply-all",             reply_all_activated},
+        {"reply-group",           reply_group_activated},
+        {"forward-attached",      forward_attached_activated},
+        {"forward-inline",        forward_inline_activated},
+        {"pipe",                  pipe_activated},
+        {"next-part",             next_part_activated},
+        {"previous-part",         previous_part_activated},
+        {"save-part",             save_part_activated},
+        {"view-source",           view_source_activated},
+        {"copy-message",          copy_message_activated},
+        {"select-text",           select_text_activated},
+        {"move-to-trash",         move_to_trash_activated},
+        {"toggle-flagged",        toggle_flagged_activated},
+        {"toggle-deleted",        toggle_deleted_activated},
+        {"toggle-new",            toggle_new_activated},
+        {"toggle-answered",       toggle_answered_activated},
+        {"store-address",         store_address_activated}
+    };
+    GtkBuilder *builder;
+    static const gchar ui_file[] = "main-window.ui";
+    GError *err = NULL;
+
+    g_action_map_add_action_entries(G_ACTION_MAP(balsa_app.application),
+                                    app_entries, G_N_ELEMENTS(app_entries),
+                                    window);
+
+    g_action_map_add_action_entries(G_ACTION_MAP(window),
+                                    win_entries, G_N_ELEMENTS(win_entries),
+                                    window);
+
+    builder = gtk_builder_new();
+    if (gtk_builder_add_from_file(builder, ui_file, &err)) {
+        gtk_application_set_app_menu(balsa_app.application,
+                                     G_MENU_MODEL(gtk_builder_get_object
+                                                  (builder, "app-menu")));
+        gtk_application_set_menubar(balsa_app.application,
+                                    G_MENU_MODEL(gtk_builder_get_object
+                                                 (builder, "menubar")));
+    } else {
+        g_print("%s error: %s\n", __func__, err->message);
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("Error adding from %s: %s\n"), ui_file,
+                          err->message);
+        g_error_free(err);
+    }
+    g_object_unref(builder);
+}
+
+/*
+ * lists of actions that are enabled or disabled as groups
+ */
+static const gchar *const mailbox_actions[] = {
+    "select-all",
+    "find", "find-next",
+    "next-message", "previous-message", "next-flagged",
+#ifdef CAN_HIDE_MENUS_AS_ACTIONS
+    "mailbox-hide-menu",
+#else
+    "hide-deleted", "hide-read", "hide-flagged", "hide-answered",
+    "hide-undeleted", "hide-unread", "hide-unflagged", "hide-unanswered",
+#endif
+    "reset-filter",
+    "mailbox-select-all", "mailbox-edit", "mailbox-delete",
+    "mailbox-expunge", "mailbox-close", "select-filters"
+#if !defined(ENABLE_TOUCH_UI)
+        , "remove-duplicates"
+#endif                          /* ENABLE_TOUCH_UI */
+};
+
+static const gchar *const message_actions[] = {
+    "reply", "reply-all", "reply-group",
+    "store-address", "view-source", "forward-attached", "forward-inline",
+    "pipe", "select-thread"
+};
+
+static const gchar *const modify_message_actions[] = {
+    "move-to-trash",
+#ifdef CAN_HIDE_MENUS_AS_ACTIONS
+    "message-toggle-flag-menu",
+#else
+    "toggle-flagged", "toggle-deleted", "toggle-new", "toggle-answered"
+#endif
+};
+
+static const gchar *const current_message_actions[] = {
+    "print",
+    "save-part", "next-part", "previous-part",
+    "copy-message", "select-text", "find-in-message"
+};
+
+/*
+ * end of GMenu stuff
+ */
+
+/*
+ * The actual BalsaWindow
+ */
+
+/*
+ * Callback for the mblist's "has-unread-mailbox" signal
+ */
+static void
+bw_enable_next_unread(BalsaWindow * window, gboolean has_unread_mailbox)
+{
+    bw_action_set_enabled(window, "next-unread", has_unread_mailbox);
+}
+
 GtkWidget *
 balsa_window_new()
 {
     BalsaWindow *window;
     BalsaToolbarModel *model;
-    GtkUIManager *ui_manager;
-    GtkAccelGroup *accel_group;
-    GError *error = NULL;
-    GtkWidget *menubar;
     GtkWidget *hbox;
-    static const gchar *const header_options[] =
-        { "NoHeaders", "SelectedHeaders", "AllHeaders" };
+    static const gchar *const header_targets[] =
+        { "none", "selected", "all" };
 #if !defined(ENABLE_TOUCH_UI)
-    static const gchar *const threading_options[] =
-        { "FlatIndex", "SimpleThreading", "JWZThreading" };
 #endif
 #if HAVE_MACOSX_DESKTOP
     IgeMacMenuGroup *group;
 #endif
-    guint i;
     GtkAdjustment *hadj, *vadj;
+    GAction *action;
 
     /* Call to register custom balsa pixmaps with GNOME_STOCK_PIXMAPS
      * - allows for grey out */
     balsa_register_pixmaps();
 
-    window = g_object_new(BALSA_TYPE_WINDOW, NULL);
+    window = g_object_new(BALSA_TYPE_WINDOW,
+                          "application", balsa_app.application,
+                          NULL);
+
+    /* Set up the GMenu structures */
+    bw_set_menus(window);
+
     window->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
     gtk_widget_show(window->vbox);
     gtk_container_add(GTK_CONTAINER(window), window->vbox);
@@ -1692,48 +2161,11 @@ balsa_window_new()
     balsa_register_pixbufs(GTK_WIDGET(window));
 
     model = balsa_window_get_toolbar_model();
-    ui_manager = balsa_window_ui_manager_new(window);
-
-    accel_group = gtk_ui_manager_get_accel_group(ui_manager);
-    gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
-    g_object_unref(accel_group);
-
-    if (!gtk_ui_manager_add_ui_from_string
-        (ui_manager, ui_description, -1, &error)) {
-        g_message("building menus failed: %s", error->message);
-        g_error_free(error);
-        g_object_unref(ui_manager);
-        g_object_unref(window);
-        return NULL;
-    }
-
-    menubar = gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
-#if HAVE_MACOSX_DESKTOP
-    ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menubar));
-    ige_mac_menu_set_quit_menu_item(GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, 
"/MainMenu/FileMenu/Quit")));
-
-    group = ige_mac_menu_add_app_menu_group();
-    ige_mac_menu_add_app_menu_item(group,
-                                  GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, 
"/MainMenu/HelpMenu/About")),
-                                   NULL);
-
-    group = ige_mac_menu_add_app_menu_group();
-    ige_mac_menu_add_app_menu_item(group,
-                                  GTK_MENU_ITEM(gtk_ui_manager_get_widget(ui_manager, 
"/MainMenu/EditMenu/Preferences")),
-                                   NULL);
-    libbalsa_macosx_menu(GTK_WIDGET(window), GTK_MENU_SHELL(menubar));
-#else
-    gtk_box_pack_start(GTK_BOX(window->vbox), menubar, FALSE, FALSE, 0);
-#endif
 
-    window->toolbar = balsa_toolbar_new(model, ui_manager);
+    window->toolbar = balsa_toolbar_new(model, G_OBJECT(window));
     gtk_box_pack_start(GTK_BOX(window->vbox), window->toolbar,
                        FALSE, FALSE, 0);
 
-    /* Now that we have installed the menubar and toolbar, we no longer
-     * need the UIManager. */
-    g_object_unref(ui_manager);
-
     window->bottom_bar = hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
     gtk_box_pack_end(GTK_BOX(window->vbox), hbox, FALSE, FALSE, 0);
 
@@ -1812,7 +2244,8 @@ balsa_window_new()
 
     /*PKGW: do it this way, without the usizes. */
 #if !defined(ENABLE_TOUCH_UI)
-    bw_set_active(window, "ShowMailboxTree", balsa_app.show_mblist, FALSE);
+    bw_action_set_boolean(window, "show-mailbox-tree",
+                          balsa_app.show_mblist);
 #endif                          /* !defined(ENABLE_TOUCH_UI) */
 
     if (balsa_app.show_mblist) {
@@ -1838,32 +2271,29 @@ balsa_window_new()
     /* set the toolbar style */
     balsa_window_refresh(window);
 
-    for (i = 0; i < G_N_ELEMENTS(header_options); i++) {
-        GtkAction *action = bw_get_action(window, header_options[i]);
-        if (i == balsa_app.shown_headers)
-            gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
-        g_signal_connect(action, "activate",
-                         G_CALLBACK(bw_header_activate_cb), window);
-    }
+    action = g_action_map_lookup_action(G_ACTION_MAP(window), "headers");
+    g_simple_action_set_state(G_SIMPLE_ACTION(action),
+                              g_variant_new_string(header_targets
+                                                   [balsa_app.
+                                                    shown_headers]));
 
 #if !defined(ENABLE_TOUCH_UI)
-    for (i = 0; i < G_N_ELEMENTS(threading_options); i++) {
-        GtkAction *action = bw_get_action(window, threading_options[i]);
-        g_signal_connect(action, "activate",
-                         G_CALLBACK(bw_threading_activate_cb), window);
-    }
+    action = g_action_map_lookup_action(G_ACTION_MAP(window), "threading");
+    g_simple_action_set_state(G_SIMPLE_ACTION(action),
+                              g_variant_new_string("flat"));
 
-    bw_set_active(window, "ShowMailboxTabs", balsa_app.show_notebook_tabs,
-                  TRUE);
-    bw_set_active(window, "Wrap", balsa_app.browse_wrap, FALSE);
+    bw_action_set_boolean(window, "show-mailbox-tabs",
+                          balsa_app.show_notebook_tabs);
+    bw_action_set_boolean(window, "wrap", balsa_app.browse_wrap);
 #else
-    bw_set_sensitive(window, "ViewFilter", balsa_app.enable_view_filter);
     g_signal_connect_after(G_OBJECT(window), "key_press_event",
                      G_CALLBACK(bw_open_mailbox_cb), NULL);
 #endif
-    bw_set_active(window, "ShowToolbar", balsa_app.show_main_toolbar, FALSE);
-    bw_set_active(window, "ShowStatusbar", balsa_app.show_statusbar, FALSE);
-    bw_set_active(window, "ShowSOSbar", balsa_app.show_sos_bar, FALSE);
+    bw_action_set_boolean(window, "show-toolbar",
+                          balsa_app.show_main_toolbar);
+    bw_action_set_boolean(window, "show-statusbar",
+                          balsa_app.show_statusbar);
+    bw_action_set_boolean(window, "show-sos-bar", balsa_app.show_sos_bar);
 
     /* Disable menu items at start up */
     balsa_window_update_book_menus(window);
@@ -1877,7 +2307,6 @@ balsa_window_new()
 #endif /*ENABLE_TOUCH_UI */
 
     /* set initial state of toggle preview pane button */
-    bw_set_active(window, "ShowPreviewPane", balsa_app.previewpane, TRUE);
 
     /* set initial state of next-unread controls */
     bw_enable_next_unread(window, FALSE);
@@ -1895,11 +2324,9 @@ balsa_window_new()
 
 #ifdef BALSA_USE_THREADS
     /* set initial state of Get-New-Mail button */
-    bw_set_sensitive(window, "GetNewMail", !checking_mail);
+    bw_action_set_enabled(window, "get-new-mail", !checking_mail);
 #endif
 
-    bw_set_visible(window, "MailboxTabMenu", FALSE);
-
     gtk_widget_show(GTK_WIDGET(window));
     return GTK_WIDGET(window);
 }
@@ -1916,8 +2343,8 @@ bw_enable_expand_collapse(BalsaWindow * window, LibBalsaMailbox * mailbox)
     enable = mailbox &&
         libbalsa_mailbox_get_threading_type(mailbox) !=
         LB_MAILBOX_THREADING_FLAT;
-    bw_set_sensitive(window, "ExpandAll", enable);
-    bw_set_sensitive(window, "CollapseAll", enable);
+    bw_action_set_enabled(window, "expand-all", enable);
+    bw_action_set_enabled(window, "collapse-all", enable);
 }
 
 /*
@@ -1958,7 +2385,8 @@ bw_enable_mailbox_menus(BalsaWindow * window, BalsaIndex * index)
         mailbox = mbnode->mailbox;
     }
     /* cppcheck-suppress nullPointer */
-    bw_set_sensitive(window, "Expunge", mailbox && !mailbox->readonly);
+    bw_action_set_enabled(window, "mailbox-expunge",
+                          mailbox && !mailbox->readonly);
 #if defined(ENABLE_TOUCH_UI)
     {gboolean can_sort, can_thread; guint i;
     static const gchar * const sort_actions[] = {
@@ -1972,21 +2400,19 @@ bw_enable_mailbox_menus(BalsaWindow * window, BalsaIndex * index)
         libbalsa_mailbox_can_do(mailbox, LIBBALSA_MAILBOX_CAN_SORT);
     can_thread = mailbox &&
         libbalsa_mailbox_can_do(mailbox, LIBBALSA_MAILBOX_CAN_THREAD);
-    for (i = 0; i < G_N_ELEMENTS(sort_actions); i++)
-        bw_set_sensitive(window, sort_actions[i], can_sort);
-    bw_set_sensitive(window, "Threaded", can_thread);
     }
 #endif
 
-    gtk_action_group_set_sensitive(window->mailbox_action_group, enable);
-    bw_set_sensitive(window, "NextMessage",
-                     index && index->next_message);
-    bw_set_sensitive(window, "PreviousMessage",
-                     index && index->prev_message);
+    bw_actions_set_enabled(window, mailbox_actions,
+                           G_N_ELEMENTS(mailbox_actions), enable);
+    bw_action_set_enabled(window, "next-message",
+                          index && index->next_message);
+    bw_action_set_enabled(window, "previous-message",
+                          index && index->prev_message);
 
 #if !defined(ENABLE_TOUCH_UI)
-    bw_set_sensitive(window, "RemoveDuplicates", mailbox
-                     && libbalsa_mailbox_can_move_duplicates(mailbox));
+    bw_action_set_enabled(window, "remove-duplicates", mailbox &&
+                          libbalsa_mailbox_can_move_duplicates(mailbox));
 #endif
 
     if (mailbox) {
@@ -2014,10 +2440,10 @@ balsa_window_update_book_menus(BalsaWindow * window)
 {
     gboolean has_books = balsa_app.address_book_list != NULL;
 
-    bw_set_sensitive(window, "AddressBook", has_books);
-    bw_set_sensitive(window, "StoreAddress", has_books
-                     && window->current_index
-                     && BALSA_INDEX(window->current_index)->current_msgno);
+    bw_app_action_set_enabled(window, "address-book",  has_books);
+    bw_action_set_enabled(window, "store-address", has_books &&
+                          window->current_index &&
+                          BALSA_INDEX(window->current_index)->current_msgno);
 }
 
 /*
@@ -2031,19 +2457,21 @@ bw_enable_message_menus(BalsaWindow * window, guint msgno)
     BalsaIndex *bindex = BALSA_INDEX(window->current_index);
 
     enable = (msgno != 0 && bindex != NULL);
-    gtk_action_group_set_sensitive(window->current_message_action_group,
-                                   enable);
+    bw_actions_set_enabled(window, current_message_actions,
+                           G_N_ELEMENTS(current_message_actions), enable);
 
     enable = (bindex != NULL
               && balsa_index_count_selected_messages(bindex) > 0);
-    gtk_action_group_set_sensitive(window->message_action_group, enable);
+    bw_actions_set_enabled(window, message_actions,
+                           G_N_ELEMENTS(message_actions), enable);
 
     enable_mod = (enable && !bindex->mailbox_node->mailbox->readonly);
-    gtk_action_group_set_sensitive(window->modify_message_action_group,
-                                   enable_mod);
+    bw_actions_set_enabled(window, modify_message_actions,
+                           G_N_ELEMENTS(modify_message_actions),
+                           enable_mod);
 
     enable_store = (enable && balsa_app.address_book_list != NULL);
-    bw_set_sensitive(window, "StoreAddress", enable_store);
+    bw_action_set_enabled(window, "store-address", enable_store);
 
 #if !defined(ENABLE_TOUCH_UI)
     balsa_window_enable_continue(window);
@@ -2058,11 +2486,13 @@ static void
 bw_enable_edit_menus(BalsaWindow * window, BalsaMessage * bm)
 {
 #if !defined(ENABLE_TOUCH_UI)
+    static const gchar * const edit_actions[] = {
+        "copy", "copy-message", "select-text"
+    };
     gboolean enable = (bm && balsa_message_can_select(bm));
 
-    bw_set_sensitive(window, "Copy",        enable);
-    bw_set_sensitive(window, "CopyMessage", enable);
-    bw_set_sensitive(window, "SelectText",  enable);
+    bw_actions_set_enabled(window, edit_actions,
+                           G_N_ELEMENTS(edit_actions), enable);
 #endif /* ENABLE_TOUCH_UI */
 #ifdef HAVE_HTML_WIDGET
     bw_enable_view_menus(window, bm);
@@ -2076,11 +2506,13 @@ bw_enable_edit_menus(BalsaWindow * window, BalsaMessage * bm)
 static void
 bw_enable_view_menus(BalsaWindow * window, BalsaMessage * bm)
 {
+    static const gchar * const zoom_actions[] = {
+        "zoom-in", "zoom-out", "zoom-normal"
+    };
     gboolean enable = bm && balsa_message_can_zoom(bm);
 
-    bw_set_sensitive(window, "ZoomIn",  enable);
-    bw_set_sensitive(window, "ZoomOut", enable);
-    bw_set_sensitive(window, "Zoom100", enable);
+    bw_actions_set_enabled(window, zoom_actions,
+                           G_N_ELEMENTS(zoom_actions), enable);
 }
 #endif                         /* HAVE_HTML_WIDGET */
 
@@ -2122,7 +2554,7 @@ enable_empty_trash(BalsaWindow * window, TrashState status)
             break;
         }
     }
-    bw_set_sensitive(window, "EmptyTrash", set);
+    bw_action_set_enabled(window, "empty-trash", set);
 }
 
 /*
@@ -2148,7 +2580,7 @@ balsa_window_enable_continue(BalsaWindow * window)
         gboolean n = !MAILBOX_OPEN(balsa_app.draftbox)
             || libbalsa_mailbox_total_messages(balsa_app.draftbox) > 0;
 
-        bw_set_sensitive(window, "Continue", n);
+        bw_action_set_enabled(window, "continue", n);
 
 /*      libbalsa_mailbox_close(balsa_app.draftbox); */
     }
@@ -2161,10 +2593,10 @@ bw_enable_part_menu_items(BalsaWindow * window)
 {
     BalsaMessage *msg = window ? BALSA_MESSAGE(window->preview) : NULL;
 
-    bw_set_sensitive(window, "NextPart",
-                     balsa_message_has_next_part(msg));
-    bw_set_sensitive(window, "PreviousPart",
-                     balsa_message_has_previous_part(msg));
+    bw_action_set_enabled(window, "next-part",
+                          balsa_message_has_next_part(msg));
+    bw_action_set_enabled(window, "previous-part",
+                          balsa_message_has_previous_part(msg));
 }
 
 static void
@@ -2173,16 +2605,9 @@ bw_set_threading_menu(BalsaWindow * window, int option)
     GtkWidget *index;
     BalsaMailboxNode *mbnode;
     LibBalsaMailbox *mailbox;
+    const gchar *const threading_types[] = { "flat", "simple", "jwz" };
 
-    switch(option) {
-    case LB_MAILBOX_THREADING_FLAT:
-    bw_set_active(window, "FlatIndex", TRUE, TRUE); break;
-    case LB_MAILBOX_THREADING_SIMPLE:
-    bw_set_active(window, "SimpleThreading", TRUE, TRUE); break;
-    case LB_MAILBOX_THREADING_JWZ:
-    bw_set_active(window, "JWZThreading", TRUE, TRUE); break;
-    default: return;
-    }
+    bw_action_set_string(window, "threading", threading_types[option]);
 
     if ((index = balsa_window_find_current_index(window))
        && (mbnode = BALSA_INDEX(index)->mailbox_node)
@@ -2191,25 +2616,6 @@ bw_set_threading_menu(BalsaWindow * window, int option)
 }
 #endif /* ENABLE_TOUCH_UI */
 
-/* Really, entire mailbox_hide_menu should be build dynamically from
- * the hide_states array since different mailboxes support different
- * set of flags/keywords. */
-static const struct {
-    LibBalsaMessageFlag flag;
-    unsigned set:1;
-    gint states_index;
-    const gchar *action_name;
-} hide_states[] = {
-    { LIBBALSA_MESSAGE_FLAG_DELETED, 1, 0, "HideDeleted"    },
-    { LIBBALSA_MESSAGE_FLAG_DELETED, 0, 1, "HideUndeleted"  },
-    { LIBBALSA_MESSAGE_FLAG_NEW,     0, 2, "HideRead"       },
-    { LIBBALSA_MESSAGE_FLAG_NEW,     1, 3, "HideUnread"     },
-    { LIBBALSA_MESSAGE_FLAG_FLAGGED, 1, 4, "HideFlagged"    },
-    { LIBBALSA_MESSAGE_FLAG_FLAGGED, 0, 5, "HideUnflagged"  },
-    { LIBBALSA_MESSAGE_FLAG_REPLIED, 1, 6, "HideAnswered"   },
-    { LIBBALSA_MESSAGE_FLAG_REPLIED, 0, 7, "HideUnanswered" }
-};
-
 static void
 bw_set_filter_menu(BalsaWindow * window, int mask)
 {
@@ -2217,16 +2623,17 @@ bw_set_filter_menu(BalsaWindow * window, int mask)
 
     for (i = 0; i < G_N_ELEMENTS(hide_states); i++) {
         gint states_index = hide_states[i].states_index;
-        GtkAction *action =
-            gtk_action_group_get_action(window->action_group,
-                                        hide_states[i].action_name);
-        g_signal_handlers_block_by_func(G_OBJECT(action),
-                                        G_CALLBACK(bw_hide_changed_cb),
+        GAction *g_action =
+            g_action_map_lookup_action(G_ACTION_MAP(window),
+                                       hide_states[i].g_action_name);
+
+        g_signal_handlers_block_by_func(G_OBJECT(g_action),
+                                        G_CALLBACK(hide_change_state),
                                         window);
-        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
-                                     (mask >> states_index) & 1);
-        g_signal_handlers_unblock_by_func(G_OBJECT(action),
-                                          G_CALLBACK(bw_hide_changed_cb),
+        bw_action_set_boolean(window, hide_states[i].g_action_name,
+                              (mask >> states_index) & 1);
+        g_signal_handlers_unblock_by_func(G_OBJECT(g_action),
+                                          G_CALLBACK(hide_change_state),
                                           window);
     }
 }
@@ -2241,7 +2648,7 @@ bw_filter_to_int(BalsaWindow * window)
     unsigned i;
     int res = 0;
     for (i = 0; i < G_N_ELEMENTS(hide_states); i++)
-        if (bw_get_active(window, hide_states[i].action_name))
+        if (bw_action_get_boolean(window, hide_states[i].g_action_name))
             res |= 1 << hide_states[i].states_index;
     return res;
 }
@@ -2327,7 +2734,6 @@ bw_notebook_label_new(BalsaMailboxNode * mbnode)
     GtkWidget *close_pix;
     GtkWidget *box;
     GtkWidget *but;
-    GtkSettings *settings;
     gint w, h;
     GtkCssProvider *css_provider;
 
@@ -2366,8 +2772,7 @@ bw_notebook_label_new(BalsaMailboxNode * mbnode)
                                    GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
     g_object_unref(css_provider);
 
-    settings = gtk_widget_get_settings(GTK_WIDGET(lab));
-    gtk_icon_size_lookup_for_settings(settings, GTK_ICON_SIZE_MENU, &w, &h);
+    gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &w, &h);
     gtk_widget_set_size_request(but, w, h);
 
     g_signal_connect(but, "clicked",
@@ -2695,6 +3100,7 @@ bw_close_mailbox_on_timer(void)
 static void
 balsa_window_destroy(GObject * object)
 {
+    g_object_set_data(object, "destroying", GINT_TO_POINTER(TRUE));
     bw_idle_remove(BALSA_WINDOW(object));
 
     if (G_OBJECT_CLASS(balsa_window_parent_class)->dispose)
@@ -2774,83 +3180,6 @@ bw_is_open_mailbox(LibBalsaMailbox *m)
     return (res != NULL);
 }
 
-static void
-bw_contents_cb(GtkAction * action, gpointer user_data)
-{
-    GdkScreen *screen;
-    GError *err = NULL;
-
-    screen = gtk_window_get_screen(user_data);
-    gtk_show_uri(screen, "help:balsa", gtk_get_current_event_time(),
-                 &err);
-    if (err) {
-        balsa_information(LIBBALSA_INFORMATION_WARNING,
-                          _("Error displaying help: %s\n"), err->message);
-        g_error_free(err);
-    }
-}
-
-static void
-bw_mailbox_tab_n_cb(GtkAction * action, gpointer data)
-{
-    GdkEvent *event;
-
-    event = gtk_get_current_event();
-    if (event->type == GDK_KEY_PRESS) {
-        gtk_notebook_set_current_page(GTK_NOTEBOOK
-                                      (BALSA_WINDOW(data)->notebook),
-                                      event->key.keyval - GDK_KEY_1);
-    }
-    gdk_event_free(event);
-}
-
-/*
- * show the about box for Balsa
- */
-static void
-bw_show_about_box(GtkAction * action, gpointer user_data)
-{
-    const gchar *authors[] = {
-        "Balsa Maintainers <balsa-maintainer theochem kth se>:",
-        "Peter Bloomfield <PeterBloomfield bellsouth net>",
-       "Bart Visscher <magick linux-fan com>",
-        "Emmanuel Allaud <e allaud wanadoo fr>",
-        "Carlos Morgado <chbm gnome org>",
-        "Pawel Salek <pawsa theochem kth se>",
-        "and many others (see AUTHORS file)",
-        NULL
-    };
-    const gchar *documenters[] = {
-        NULL
-    };
-
-    const gchar *translator_credits = _("translator-credits");
-    /* FIXME: do we need error handling for this? */
-    GdkPixbuf *balsa_logo =
-        gdk_pixbuf_new_from_file(BALSA_DATA_PREFIX
-                                 "/pixmaps/balsa_logo.png", NULL);
-
-    gtk_show_about_dialog(GTK_WINDOW(user_data),
-                          "version", BALSA_VERSION,
-                          "copyright",
-                          "Copyright \xc2\xa9 1997-2013 The Balsa Developers",
-                          "comments",
-                          _("The Balsa email client is part of "
-                            "the GNOME desktop environment."),
-                          "authors", authors,
-                          "documenters", documenters,
-                          /* license ? */
-                          "title", _("About Balsa"),
-                          "translator-credits",
-                          strcmp(translator_credits, "translator-credits") ?
-                         translator_credits : NULL,
-                         "logo", balsa_logo,
-                          "website", "http://balsa.gnome.org";,
-                          "wrap-license", TRUE,
-                          NULL);
-    g_object_unref(balsa_logo);
-}
-
 /* Check all mailboxes in a list
  *
  */
@@ -2991,7 +3320,7 @@ bw_mailbox_check(LibBalsaMailbox * mailbox, BalsaWindow * window)
  * Callbacks
  */
 
-/* check_new_messages_cb:
+/* bw_check_new_messages:
    check new messages the data argument is the BalsaWindow pointer
    or NULL.
 */
@@ -3019,7 +3348,7 @@ check_new_messages_real(BalsaWindow * window, int type)
     }
     checking_mail = 1;
     if (window)
-        bw_set_sensitive(window, "GetNewMail", FALSE);
+        bw_action_set_enabled(window, "get-new-mail", FALSE);
 
     quiet_check = (type == TYPE_CALLBACK)
         ? 0 : balsa_app.quiet_background_check;
@@ -3050,7 +3379,7 @@ check_new_messages_real(BalsaWindow * window, int type)
 #else
 
     if (window)
-        bw_set_sensitive(window, "GetNewMail", FALSE);
+        bw_action_set_enabled(window, "get-new-mail", FALSE);
 
     bw_check_mailbox_list(window, balsa_app.inbox_input);
 
@@ -3064,29 +3393,15 @@ check_new_messages_real(BalsaWindow * window, int type)
     g_slist_free(list);
 
     if (window)
-        bw_set_sensitive(window, "GetNewMail", TRUE);
+        bw_action_set_enabled(window, "get-new-mail", TRUE);
 
     if (window->network_available)
         time(&window->last_check_time);
 #endif
 }
 
-/* bw_send_receive_messages_cb:
-   check messages first to satisfy those that use smtp-after-pop.
-*/
 static void
-bw_send_receive_messages_cb(GtkAction * action, gpointer data)
-{
-    check_new_messages_cb(action, data);
-    libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url,
-#if ENABLE_ESMTP
-                           balsa_app.smtp_servers,
-#endif /* ENABLE_ESMTP */
-                          balsa_app.debug);
-}
-
-void
-check_new_messages_cb(GtkAction * action, gpointer data)
+bw_check_new_messages(gpointer data)
 {
     check_new_messages_real(data, TYPE_CALLBACK);
 
@@ -3133,53 +3448,6 @@ check_new_messages_count(LibBalsaMailbox * mailbox, gboolean notify)
     info->has_unread_messages = mailbox->has_unread_messages;
 }
 
-/* bw_send_outbox_messages_cb:
-   tries again to send the messages queued in outbox.
-*/
-
-static void
-bw_send_outbox_messages_cb(GtkAction * action, gpointer data)
-{
-    libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url,
-#if ENABLE_ESMTP
-                           balsa_app.smtp_servers,
-#endif /* ENABLE_ESMTP */
-                          balsa_app.debug);
-}
-
-/* Callback for `Page setup' item on the `File' menu */
-static void
-bw_page_setup_cb(GtkAction * action, gpointer data)
-{
-    message_print_page_setup(GTK_WINDOW(data));
-}
-
-/* Callback for `Print current message' item on the `File' menu,
- * and the toolbar button. */
-static void
-bw_message_print_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-    BalsaIndex *bindex;
-
-    g_return_if_fail(data);
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    if (!index)
-        return;
-
-    bindex = BALSA_INDEX(index);
-    if (bindex->current_msgno) {
-        LibBalsaMessage *message =
-            libbalsa_mailbox_get_message(bindex->mailbox_node->mailbox,
-                                         bindex->current_msgno);
-        if (!message)
-            return;
-        message_print(message, GTK_WINDOW(data));
-        g_object_unref(message);
-    }
-}
-
 /* this one is called only in the threaded code */
 #if defined(BALSA_USE_THREADS)
 static void
@@ -3210,7 +3478,7 @@ bw_mailbox_check(LibBalsaMailbox * mailbox, BalsaWindow * window)
 static gboolean
 bw_check_messages_thread_idle_cb(BalsaWindow * window)
 {
-    bw_set_sensitive(window, "GetNewMail", TRUE);
+    bw_action_set_enabled(window, "get-new-mail", TRUE);
     g_object_unref(window);
 
     return FALSE;
@@ -3680,7 +3948,7 @@ bw_change_connection_status_idle(gpointer user_data)
         difftime(time(NULL), window->last_check_time) >
         balsa_app.check_mail_timer * 60) {
         /* Check the mail now, and reset the timer */
-        check_new_messages_cb(NULL, window);
+        bw_check_new_messages(window);
     }
 
     return FALSE;
@@ -3694,593 +3962,6 @@ balsa_window_find_current_index(BalsaWindow * window)
     return window->current_index;
 }
 
-
-static void
-bw_new_message_cb(GtkAction * action, gpointer data)
-{
-    BalsaSendmsg *smwindow;
-
-    smwindow = sendmsg_window_compose();
-
-#if !defined(ENABLE_TOUCH_UI)
-    g_signal_connect(G_OBJECT(smwindow->window), "destroy",
-                     G_CALLBACK(bw_send_msg_window_destroy_cb), data);
-#endif /*ENABLE_TOUCH_UI */
-}
-
-
-static void
-bw_replyto_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_reply(balsa_window_find_current_index
-                        (BALSA_WINDOW(data)));
-}
-
-static void
-bw_replytoall_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_replytoall(balsa_window_find_current_index
-                             (BALSA_WINDOW(data)));
-}
-
-static void
-bw_replytogroup_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_replytogroup(balsa_window_find_current_index
-                               (BALSA_WINDOW(data)));
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_forward_message_attached_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_forward_attached(balsa_window_find_current_index
-                                   (BALSA_WINDOW(data)));
-}
-
-static void
-bw_forward_message_inline_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_forward_inline(balsa_window_find_current_index
-                                 (BALSA_WINDOW(data)));
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_forward_message_default_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_forward_default(balsa_window_find_current_index
-                                  (BALSA_WINDOW(data)));
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_pipe_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_pipe(BALSA_INDEX
-                     (balsa_window_find_current_index
-                      (BALSA_WINDOW(data))));
-}
-
-static void
-bw_select_thread_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_select_thread(BALSA_INDEX
-                              (balsa_window_find_current_index
-                               (BALSA_WINDOW(data))));
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_continue_message_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-
-    if (index && BALSA_INDEX(index)->mailbox_node->mailbox == balsa_app.draftbox)
-        balsa_message_continue(BALSA_INDEX(index));
-    else
-        balsa_mblist_open_mailbox(balsa_app.draftbox);
-}
-
-
-static void
-bw_next_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_select_next(
-        BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))));
-}
-
-/* Select next unread message, changing mailboxes if necessary;
- * returns TRUE if mailbox was changed. */
-gboolean
-balsa_window_next_unread(BalsaWindow * window)
-{
-    BalsaIndex *index =
-        BALSA_INDEX(balsa_window_find_current_index(window));
-    LibBalsaMailbox *mailbox = index ? index->mailbox_node->mailbox : NULL;
-
-    if (libbalsa_mailbox_get_unread(mailbox) > 0) {
-        if (!balsa_index_select_next_unread(index)) {
-            /* All unread messages must be hidden; we assume that the
-             * user wants to see them, and try again. */
-            bw_reset_filter_cb(NULL, window);
-            balsa_index_select_next_unread(index);
-        }
-        return FALSE;
-    }
-
-    mailbox = bw_next_unread_mailbox(mailbox);
-    if (!mailbox || libbalsa_mailbox_get_unread(mailbox) == 0)
-        return FALSE;
-
-    if (balsa_app.ask_before_select) {
-        GtkWidget *dialog;
-        gint response;
-
-        dialog =
-            gtk_message_dialog_new(GTK_WINDOW(window), 0,
-                                   GTK_MESSAGE_QUESTION,
-                                   GTK_BUTTONS_YES_NO,
-                                   _("The next unread message is in %s"),
-                                   mailbox->name);
-#if HAVE_MACOSX_DESKTOP
-        libbalsa_macosx_menu_for_parent(dialog, GTK_WINDOW(window));
-#endif
-        gtk_message_dialog_format_secondary_text
-            (GTK_MESSAGE_DIALOG(dialog),
-             _("Do you want to select %s?"), mailbox->name);
-        gtk_dialog_set_default_response(GTK_DIALOG(dialog),
-                                        GTK_RESPONSE_YES);
-        response = gtk_dialog_run(GTK_DIALOG(dialog));
-        gtk_widget_destroy(dialog);
-        if (response != GTK_RESPONSE_YES)
-            return FALSE;
-    }
-
-    balsa_mblist_open_mailbox(mailbox);
-    index = balsa_find_index_by_mailbox(mailbox);
-    if (index)
-        balsa_index_select_next_unread(index);
-    else
-        g_object_set_data(G_OBJECT(mailbox),
-                          BALSA_INDEX_VIEW_ON_OPEN, GINT_TO_POINTER(TRUE));
-    return TRUE;
-}
-
-static void
-bw_next_unread_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_window_next_unread(BALSA_WINDOW(data));
-}
-
-static void
-bw_next_flagged_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_select_next_flagged(
-        BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))));
-}
-
-static void
-bw_previous_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_select_previous(
-        BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))));
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_next_part_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    balsa_message_next_part(BALSA_MESSAGE(bw->preview));
-}
-
-static void
-bw_previous_part_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    balsa_message_previous_part(BALSA_MESSAGE(bw->preview));
-}
-#endif /* ENABLE_TOUCH_UI */
-
-/* Edit menu callbacks. */
-static void
-bw_copy_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    guint signal_id;
-    GtkWidget *focus_widget = gtk_window_get_focus(GTK_WINDOW(bw));
-
-    if (!focus_widget)
-       return;
-
-    signal_id = g_signal_lookup("copy-clipboard",
-                                G_TYPE_FROM_INSTANCE(focus_widget));
-    if (signal_id)
-        g_signal_emit(focus_widget, signal_id, (GQuark) 0);
-#ifdef HAVE_HTML_WIDGET
-    else if (libbalsa_html_can_select(focus_widget))
-       libbalsa_html_copy(focus_widget);
-#endif /* HAVE_HTML_WIDGET */
-}
-
-static void
-bw_select_all_cb(GtkAction * action, gpointer data)
-{
-    balsa_window_select_all(data);
-}
-
-/* Message menu callbacks. */
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_message_copy_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    if (balsa_message_grab_focus(BALSA_MESSAGE(bw->preview)))
-        bw_copy_cb(action, data);
-}
-
-static void
-bw_message_select_all_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    if (balsa_message_grab_focus(BALSA_MESSAGE(bw->preview)))
-       balsa_window_select_all(data);
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_save_current_part_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    balsa_message_save_current_part(BALSA_MESSAGE(bw->preview));
-}
-
-static void
-bw_view_msg_source_cb(GtkAction * action, gpointer data)
-{
-    BalsaWindow *bw;
-    GtkWidget *bindex;
-    GList *messages, *list;
-    bw = BALSA_WINDOW(data);
-
-    bindex = balsa_window_find_current_index(bw);
-    g_return_if_fail(bindex);
-    messages = balsa_index_selected_list(BALSA_INDEX(bindex));
-    for (list = messages; list; list = list->next) {
-       LibBalsaMessage *message = list->data;
-
-       libbalsa_show_message_source(balsa_app.application,
-                                     message, balsa_app.message_font,
-                                    &balsa_app.source_escape_specials,
-                                     &balsa_app.source_width,
-                                     &balsa_app.source_height);
-    }
-
-    g_list_foreach(messages, (GFunc)g_object_unref, NULL);
-    g_list_free(messages);
-}
-
-static void
-bw_trash_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_message_move_to_trash(balsa_window_find_current_index
-                                (BALSA_WINDOW(data)));
-}
-
-static void
-bw_toggle_deleted_message_cb(GtkAction * action, gpointer data)
-{
-    LibBalsaMessageFlag f = LIBBALSA_MESSAGE_FLAG_DELETED;
-    balsa_index_toggle_flag
-        (BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))),
-         f);
-}
-
-
-static void
-bw_toggle_flagged_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_toggle_flag
-        (BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))),
-         LIBBALSA_MESSAGE_FLAG_FLAGGED);
-}
-
-static void
-bw_toggle_new_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_toggle_flag
-        (BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))),
-         LIBBALSA_MESSAGE_FLAG_NEW);
-}
-
-static void
-bw_toggle_answered_message_cb(GtkAction * action, gpointer data)
-{
-    balsa_index_toggle_flag
-        (BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(data))),
-         LIBBALSA_MESSAGE_FLAG_REPLIED);
-}
-
-static void
-bw_store_address_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    GList *messages;
-
-    g_assert(index != NULL);
-
-    messages = balsa_index_selected_list(BALSA_INDEX(index));
-    balsa_store_address_from_messages(messages);
-    g_list_foreach(messages, (GFunc)g_object_unref, NULL);
-    g_list_free(messages);
-}
-
-#if defined(ENABLE_TOUCH_UI)
-static void
-bw_set_sort_menu(BalsaWindow *window,
-                 LibBalsaMailboxSortFields col,
-                 LibBalsaMailboxSortType   order)
-{
-    const gchar *action_name;
-    GtkAction *action;
-
-    switch(col) {
-    case LB_MAILBOX_SORT_DATE:
-    case LB_MAILBOX_SORT_NO:      action_name = "ByArrival"; break;
-    case LB_MAILBOX_SORT_SENDER:  action_name = "BySender";  break;
-    case LB_MAILBOX_SORT_SUBJECT: action_name = "BySubject"; break;
-    case LB_MAILBOX_SORT_SIZE:    action_name = "BySize";    break;
-    case LB_MAILBOX_SORT_THREAD:  action_name = "Threaded";  break;
-    default: return;
-    }
-
-    action =
-        gtk_action_group_get_action(window->mailbox_action_group,
-                                    action_name);
-    g_signal_handlers_block_by_func(G_OBJECT(action),
-                                    G_CALLBACK(bw_sort_change_cb),
-                                    window);
-    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
-    g_signal_handlers_unblock_by_func(G_OBJECT(action),
-                                      G_CALLBACK(bw_sort_change_cb),
-                                      window);
-
-    action =
-        gtk_action_group_get_action(window->action_group,
-                                    "SortDescending");
-    g_signal_handlers_block_by_func(G_OBJECT(action),
-                                    G_CALLBACK(bw_sort_change_cb),
-                                    window);
-    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
-                                 order == LB_MAILBOX_SORT_TYPE_DESC);
-    g_signal_handlers_unblock_by_func(G_OBJECT(action),
-                                      G_CALLBACK(bw_sort_change_cb),
-                                      window);
-
-    gtk_action_set_sensitive(action, strcmp(action_name, "Threaded") != 0);
-}
-
-static void
-bw_sort_change_cb(GtkRadioAction *action, GtkRadioAction *current, gpointer data)
-{
-    BalsaWindow *window = BALSA_WINDOW(data);
-    LibBalsaMailboxSortFields key;
-    LibBalsaMailboxSortType   order;
-    GtkWidget       *bindex;
-    LibBalsaMailbox *mailbox;
-    gint             col;
-
-    bindex = balsa_window_find_current_index(window);
-    if(!bindex)
-        return;
-
-    key = gtk_radio_action_get_current_value(action);
-    mailbox = BALSA_INDEX(bindex)->mailbox_node->mailbox;
-
-    switch(key) {
-    case LB_MAILBOX_SORT_NO:      col = LB_MBOX_MSGNO_COL;   break;
-    case LB_MAILBOX_SORT_SENDER:  col = LB_MBOX_FROM_COL;    break;
-    case LB_MAILBOX_SORT_SUBJECT: col = LB_MBOX_SUBJECT_COL; break;
-    case LB_MAILBOX_SORT_DATE:    col = LB_MBOX_DATE_COL;    break;
-    case LB_MAILBOX_SORT_SIZE:    col = LB_MBOX_SIZE_COL;    break;
-    case LB_MAILBOX_SORT_THREAD:
-        libbalsa_mailbox_set_sort_field(mailbox, key);
-        balsa_index_set_threading_type(BALSA_INDEX(bindex),
-                                       LB_MAILBOX_THREADING_JWZ);
-        bw_set_sensitive(window, "SortDescending", FALSE);
-        return;
-    default: return;
-    }
-    bw_set_sensitive(window, "SortDescending", TRUE);
-    if(libbalsa_mailbox_get_threading_type(mailbox)
-       != LB_MAILBOX_THREADING_FLAT)
-        balsa_index_set_threading_type(BALSA_INDEX(bindex),
-                                       LB_MAILBOX_THREADING_FLAT);
-    order = libbalsa_mailbox_get_sort_type(mailbox);
-    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(mailbox),
-                                         col,
-                                         order == LB_MAILBOX_SORT_TYPE_ASC
-                                         ? GTK_SORT_ASCENDING
-                                         : GTK_SORT_DESCENDING);
-}
-
-static void
-bw_toggle_order_cb(GtkToggleAction * action, gpointer data)
-{
-    LibBalsaMailboxSortType   order;
-    GtkWidget       *bindex;
-    LibBalsaMailbox *mailbox;
-    gint             col;
-
-    bindex = balsa_window_find_current_index(BALSA_WINDOW(data));
-    if(!bindex)
-        return;
-    mailbox = BALSA_INDEX(bindex)->mailbox_node->mailbox;
-    order = gtk_toggle_action_get_active(action)
-        ? LB_MAILBOX_SORT_TYPE_DESC :  LB_MAILBOX_SORT_TYPE_ASC;
-
-    switch(libbalsa_mailbox_get_sort_field(mailbox)) {
-    case LB_MAILBOX_SORT_NO:      col = LB_MBOX_MSGNO_COL;   break;
-    case LB_MAILBOX_SORT_SENDER:  col = LB_MBOX_FROM_COL;    break;
-    case LB_MAILBOX_SORT_SUBJECT: col = LB_MBOX_SUBJECT_COL; break;
-    case LB_MAILBOX_SORT_DATE:    col = LB_MBOX_DATE_COL;    break;
-    case LB_MAILBOX_SORT_SIZE:    col = LB_MBOX_SIZE_COL;    break;
-    default:
-    case LB_MAILBOX_SORT_THREAD:
-        g_warning("This should not be possible"); return;
-    }
-    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(mailbox),
-                                         col,
-                                         order == LB_MAILBOX_SORT_TYPE_ASC
-                                         ? GTK_SORT_ASCENDING
-                                         : GTK_SORT_DESCENDING);
-}
-
-#endif /* ENABLE_TOUCH_UI */
-static void
-bw_wrap_message_cb(GtkToggleAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-
-    balsa_app.browse_wrap = gtk_toggle_action_get_active(action);
-
-    balsa_message_set_wrap(BALSA_MESSAGE(bw->preview),
-                           balsa_app.browse_wrap);
-    refresh_preferences_manager();
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_show_helper(GtkToggleAction * action, gboolean * active,
-               GtkWidget * widget)
-{
-    if ((*active = gtk_toggle_action_get_active(action)))
-        gtk_widget_show(widget);
-    else
-        gtk_widget_hide(widget);
-}
-
-static void
-bw_show_toolbar_cb(GtkToggleAction * action, gpointer data)
-{
-    bw_show_helper(action, &balsa_app.show_main_toolbar,
-                   BALSA_WINDOW(data)->toolbar);
-}
-
-static void
-bw_show_statusbar_cb(GtkToggleAction * action, gpointer data)
-{
-    bw_show_helper(action, &balsa_app.show_statusbar,
-                   BALSA_WINDOW(data)->bottom_bar);
-}
-
-static void
-bw_show_sos_bar_cb(GtkToggleAction * action, gpointer data)
-{
-    bw_show_helper(action, &balsa_app.show_sos_bar,
-                   BALSA_WINDOW(data)->sos_bar);
-}
-#endif
-
-/*
- * Callback for the "activate" signal of the View menu's header options.
- * We use this instead of the GtkRadioAction's "changed" signal so that
- * we can respond to a click on the current choice.
- */
-static void
-bw_header_activate_cb(GtkAction * action, gpointer data)
-{
-    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) {
-        ShownHeaders sh =
-            gtk_radio_action_get_current_value(GTK_RADIO_ACTION(action));
-        BalsaWindow *bw = BALSA_WINDOW(data);
-
-        balsa_app.shown_headers = sh;
-        bw_reset_show_all_headers(bw);
-        balsa_message_set_displayed_headers(BALSA_MESSAGE(bw->preview),
-                                            sh);
-    }
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-/*
- * Callback for the "activate" signal of the View menu's threading options.
- * We use this instead of the GtkRadioAction's "changed" signal so that
- * we can respond to a click on the current choice.
- */
-static void
-bw_threading_activate_cb(GtkAction * action, gpointer data)
-{
-    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))) {
-        BalsaWindow *bw = BALSA_WINDOW(data);
-        GtkWidget *index;
-        LibBalsaMailboxThreadingType type;
-        BalsaMailboxNode *mbnode;
-        LibBalsaMailbox *mailbox;
-
-        index = balsa_window_find_current_index(bw);
-        g_return_if_fail(index != NULL);
-
-        type =
-            gtk_radio_action_get_current_value(GTK_RADIO_ACTION(action));
-        balsa_index_set_threading_type(BALSA_INDEX(index), type);
-
-        /* bw->current_index may have been destroyed and cleared during
-         * set-threading: */
-        index = balsa_window_find_current_index(bw);
-        if (index && (mbnode = BALSA_INDEX(index)->mailbox_node)
-            && (mailbox = mbnode->mailbox))
-            bw_enable_expand_collapse(bw, mailbox);
-    }
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_expand_all_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    g_return_if_fail(index);
-    balsa_index_update_tree(BALSA_INDEX(index), TRUE);
-}
-
-static void
-bw_collapse_all_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    g_return_if_fail(index);
-    balsa_index_update_tree(BALSA_INDEX(index), FALSE);
-}
-
-#ifdef HAVE_HTML_WIDGET
-static void
-bw_zoom_in_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *bm = BALSA_WINDOW(data)->preview;
-    balsa_message_zoom(BALSA_MESSAGE(bm), 1);
-}
-
-static void
-bw_zoom_out_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *bm = BALSA_WINDOW(data)->preview;
-    balsa_message_zoom(BALSA_MESSAGE(bm), -1);
-}
-
-static void
-bw_zoom_100_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *bm = BALSA_WINDOW(data)->preview;
-    balsa_message_zoom(BALSA_MESSAGE(bm), 0);
-}
-#endif                         /* HAVE_HTML_WIDGET */
-
 #if defined(ENABLE_TOUCH_UI)
 static gboolean
 bw_open_mailbox_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
@@ -4300,30 +3981,8 @@ bw_open_mailbox_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
     balsa_mblist_open_mailbox(mailbox);
     return TRUE;
 }
-
-static void
-bw_enable_view_filter_cb(GtkToggleAction * action, gpointer data)
-{
-    BalsaWindow *mw       = BALSA_WINDOW(data);
-    GtkWidget *parent_box = gtk_widget_get_parent(mw->sos_entry);
-    balsa_app.enable_view_filter = gtk_toggle_action_get_active(action);
-    if(balsa_app.enable_view_filter)
-        gtk_widget_show(parent_box);
-    else
-        gtk_widget_hide(parent_box);
-}
-
 #endif /* ENABLE_TOUCH_UI */
 
-static void
-bw_address_book_cb(GtkWindow *widget, gpointer data)
-{
-    GtkWidget *ab;
-
-    ab = balsa_ab_window_new(FALSE, GTK_WINDOW(data));
-    gtk_widget_show(GTK_WIDGET(ab));
-}
-
 static GtkToggleButton*
 bw_add_check_button(GtkWidget* grid, const gchar* label, gint x, gint y)
 {
@@ -4539,7 +4198,7 @@ bw_find_real(BalsaWindow * window, BalsaIndex * bindex, gboolean again)
                }
                break;
             case FIND_RESPONSE_RESET:
-               bw_reset_filter_cb(NULL, window);
+               bw_reset_filter(window);
                /* fall through */
             default:
                ok = GTK_RESPONSE_CANCEL;
@@ -4578,108 +4237,6 @@ bw_find_real(BalsaWindow * window, BalsaIndex * bindex, gboolean again)
 }
 
 static void
-bw_find_cb(GtkAction * action,gpointer data)
-{
-    BalsaWindow *window = data;
-    GtkWidget * bindex;
-    if ((bindex=balsa_window_find_current_index(window)))
-       bw_find_real(window, BALSA_INDEX(bindex),FALSE);
-}
-
-static void
-bw_find_again_cb(GtkAction * action,gpointer data)
-{
-    BalsaWindow *window = data;
-    GtkWidget * bindex;
-    if ((bindex=balsa_window_find_current_index(window)))
-       bw_find_real(window, BALSA_INDEX(bindex), TRUE);
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_find_in_message_cb(GtkAction * action,gpointer data)
-{
-    BalsaWindow *window = data;
-    if (balsa_app.previewpane)
-        balsa_message_find_in_message(BALSA_MESSAGE(window->preview));
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_filter_dlg_cb(GtkAction * action, gpointer data)
-{
-    filters_edit_dialog();
-}
-
-static void
-bw_filter_export_cb(GtkAction * action, gpointer data)
-{
-    filters_export_dialog();
-}
-
-static void
-bw_filter_run_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index = balsa_window_find_current_index(BALSA_WINDOW(data));
-
-    if (index)
-        filters_run_dialog(BALSA_INDEX(index)->mailbox_node->mailbox);
-    else
-       /* FIXME : Perhaps should we be able to apply filters on folders (ie recurse on all mailboxes in it),
-          but there are problems of infinite recursion (when one mailbox being filtered is also the 
destination
-          of the filter action (eg a copy)). So let's see that later :) */
-       balsa_information(LIBBALSA_INFORMATION_WARNING,
-                          _("You can apply filters only on mailbox\n"));
-}
-
-#if !defined(ENABLE_TOUCH_UI)
-static void
-bw_remove_duplicates_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    if (index) {
-        LibBalsaMailbox *mailbox =
-            BALSA_INDEX(index)->mailbox_node->mailbox;
-        GError *err = NULL;
-        gint dup_count = libbalsa_mailbox_move_duplicates(mailbox, NULL, &err);
-        if (err) {
-            balsa_information(LIBBALSA_INFORMATION_WARNING,
-                              _("Removing duplicates failed: %s"),
-                              err->message);
-            g_error_free(err);
-        } else {
-           if(dup_count)
-                balsa_information(LIBBALSA_INFORMATION_MESSAGE,
-                                  ngettext("Removed %d duplicate",
-                                           "Removed %d duplicates",
-                                           dup_count), dup_count);
-           else
-               balsa_information(LIBBALSA_INFORMATION_MESSAGE,
-                                 _("No duplicates found"));
-       }
-
-    }
-}
-#endif /* ENABLE_TOUCH_UI */
-
-static void
-bw_empty_trash_cb(GtkAction * action, gpointer data)
-{
-    empty_trash(BALSA_WINDOW(data));
-}
-
-/* closes the mailbox on the notebook's active page */
-static void
-bw_mailbox_close_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index = balsa_window_find_current_index(BALSA_WINDOW(data));
-
-    if (index)
-        balsa_mblist_close_mailbox(BALSA_INDEX(index)->mailbox_node->
-                                   mailbox);
-}
-
-static void
 bw_mailbox_tab_close_cb(GtkWidget * widget, gpointer data)
 {
     GtkWidget * window = gtk_widget_get_toplevel(widget);
@@ -4717,52 +4274,23 @@ bw_get_view_filter(BalsaWindow *window)
 }
 
 static void
-bw_hide_changed_cb(GtkToggleAction * toggle_action, gpointer data)
+bw_hide_changed_set_view_filter(BalsaWindow * window)
 {
+    GtkWidget *index;
     LibBalsaMailbox *mailbox;
-    BalsaWindow *bw = BALSA_WINDOW(data);
-    GtkWidget *index = balsa_window_find_current_index(bw);
-    LibBalsaCondition *filter;
     gint mask;
+    LibBalsaCondition *filter;
 
-    /* PART 1: assure menu consistency */
-    if (gtk_toggle_action_get_active(toggle_action)) {
-        /* we may need to deactivate coupled negated flag. */
-        const gchar *action_name =
-            gtk_action_get_name(GTK_ACTION(toggle_action));
-        unsigned curr_idx, i;
-
-        for (i = 0; i < G_N_ELEMENTS(hide_states); i++)
-            if (strcmp(action_name, hide_states[i].action_name) == 0)
-                break;
-        g_assert(i < G_N_ELEMENTS(hide_states));
-        curr_idx = hide_states[i].states_index;
-
-        for (i = 0; i < G_N_ELEMENTS(hide_states); i++) {
-            int states_idx = hide_states[i].states_index;
-
-            if (!bw_get_active(bw, hide_states[i].action_name))
-                continue;
-
-            if (hide_states[states_idx].flag == hide_states[curr_idx].flag
-                && hide_states[states_idx].set !=
-                hide_states[curr_idx].set) {
-                bw_set_active(bw, hide_states[i].action_name, FALSE, FALSE);
-                return; /* triggered menu change will do the job */
-            }
-        }
-    }
-
+    index = balsa_window_find_current_index(window);
     if(!index)
         return;
 
-    /* PART 2: do the job. */
     mailbox = BALSA_INDEX(index)->mailbox_node->mailbox;
     /* Store the new filter mask in the mailbox view before we set the
      * view filter; rethreading triggers bw_set_filter_menu,
      * which retrieves the mask from the mailbox view, and we want it to
      * be the new one. */
-    mask = bw_filter_to_int(bw);
+    mask = bw_filter_to_int(window);
     libbalsa_mailbox_set_filter(mailbox, mask);
 
     /* Set the flags part of this filter as persistent: */
@@ -4771,7 +4299,7 @@ bw_hide_changed_cb(GtkToggleAction * toggle_action, gpointer data)
     libbalsa_condition_unref(filter);
     libbalsa_mailbox_make_view_filter_persistent(mailbox);
 
-    filter = bw_get_view_filter(bw);
+    filter = bw_get_view_filter(window);
     /* libbalsa_mailbox_set_view_filter() will ref the
      * filter.  We need also to rethread to take into account that
      * some messages might have been removed or added to the view. */
@@ -4781,9 +4309,8 @@ bw_hide_changed_cb(GtkToggleAction * toggle_action, gpointer data)
 }
 
 static void
-bw_reset_filter_cb(GtkAction * action, gpointer data)
+bw_reset_filter(BalsaWindow * bw)
 {
-    BalsaWindow *bw = BALSA_WINDOW(data);
     BalsaIndex *bindex = BALSA_INDEX(balsa_window_find_current_index(bw));
 
     /* do it by resetting the sos filder */
@@ -4791,15 +4318,6 @@ bw_reset_filter_cb(GtkAction * action, gpointer data)
     bw_set_view_filter(bw, bindex->filter_no, bw->sos_entry);
 }
 
-static void
-bw_mailbox_expunge_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    balsa_index_expunge(BALSA_INDEX(index));
-}
-
 /* empty_trash:
    empty the trash mailbox.
 */
@@ -4861,20 +4379,6 @@ bw_show_mbtree(BalsaWindow * bw)
     }
 }
 
-static void
-bw_show_mbtree_cb(GtkToggleAction * action, gpointer data)
-{
-    balsa_app.show_mblist = gtk_toggle_action_get_active(action);
-    bw_show_mbtree(BALSA_WINDOW(data));
-}
-
-static void
-bw_show_mbtabs_cb(GtkToggleAction * action, gpointer data)
-{
-    balsa_app.show_notebook_tabs = gtk_toggle_action_get_active(action);
-    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(balsa_app.notebook),
-                               balsa_app.show_notebook_tabs);
-}
 #endif /* ENABLE_TOUCH_UI */
 
 void
@@ -5385,60 +4889,6 @@ balsa_window_increment_progress(BalsaWindow * window, gdouble fraction,
  * End of progress bar functions.
  */
 
-static void
-bw_ident_manage_dialog_cb(GtkAction * action, gpointer user_data)
-{
-    libbalsa_identity_config_dialog(GTK_WINDOW(user_data),
-                                    &balsa_app.identities,
-                                    &balsa_app.current_ident,
-#if ENABLE_ESMTP
-                                   balsa_app.smtp_servers,
-#endif /* ENABLE_ESMTP */
-                                    (void(*)(gpointer))
-                                    balsa_identities_changed);
-}
-
-
-static void
-bw_mark_all_cb(GtkAction * action, gpointer data)
-{
-    GtkWidget *index;
-
-    index = balsa_window_find_current_index(BALSA_WINDOW(data));
-    g_return_if_fail(index != NULL);
-
-    gtk_widget_grab_focus(index);
-    balsa_window_select_all(data);
-}
-
-static void
-bw_show_all_headers_tool_cb(GtkToggleAction * action, gpointer data)
-{
-    BalsaWindow *bw = BALSA_WINDOW(data);
-
-    balsa_app.show_all_headers = gtk_toggle_action_get_active(action);
-    balsa_message_set_displayed_headers(BALSA_MESSAGE(bw->preview),
-                                        balsa_app.show_all_headers ?
-                                        HEADERS_ALL :
-                                        balsa_app.shown_headers);
-}
-
-static void
-bw_reset_show_all_headers(BalsaWindow * window)
-{
-    if (balsa_app.show_all_headers) {
-        bw_set_active(window, "ShowAllHeaders", FALSE, TRUE);
-        balsa_app.show_all_headers = FALSE;
-    }
-}
-
-static void
-bw_show_preview_pane_cb(GtkToggleAction * action, gpointer data)
-{
-    balsa_app.previewpane = gtk_toggle_action_get_active(action);
-    balsa_window_refresh(BALSA_WINDOW(data));
-}
-
 /* browse_wrap can also be changed in the preferences window
  *
  * update_view_menu is called to synchronize the view menu check item
@@ -5447,7 +4897,7 @@ void
 update_view_menu(BalsaWindow * window)
 {
 #if !defined(ENABLE_TOUCH_UI)
-    bw_set_active(window, "Wrap", balsa_app.browse_wrap, TRUE);
+    bw_action_set_boolean(window, "wrap", balsa_app.browse_wrap);
     balsa_message_set_wrap(BALSA_MESSAGE(window->preview),
                            balsa_app.browse_wrap);
 #endif /* ENABLE_TOUCH_UI */
@@ -5559,3 +5009,60 @@ balsa_window_set_statusbar(BalsaWindow * window, LibBalsaMailbox * mailbox)
 
     g_string_free(desc, TRUE);
 }
+
+/* Select next unread message, changing mailboxes if necessary;
+ * returns TRUE if mailbox was changed. */
+gboolean
+balsa_window_next_unread(BalsaWindow * window)
+{
+    BalsaIndex *index =
+        BALSA_INDEX(balsa_window_find_current_index(window));
+    LibBalsaMailbox *mailbox = index ? index->mailbox_node->mailbox : NULL;
+
+    if (libbalsa_mailbox_get_unread(mailbox) > 0) {
+        if (!balsa_index_select_next_unread(index)) {
+            /* All unread messages must be hidden; we assume that the
+             * user wants to see them, and try again. */
+            bw_reset_filter(window);
+            balsa_index_select_next_unread(index);
+        }
+        return FALSE;
+    }
+
+    mailbox = bw_next_unread_mailbox(mailbox);
+    if (!mailbox || libbalsa_mailbox_get_unread(mailbox) == 0)
+        return FALSE;
+
+    if (balsa_app.ask_before_select) {
+        GtkWidget *dialog;
+        gint response;
+
+        dialog =
+            gtk_message_dialog_new(GTK_WINDOW(window), 0,
+                                   GTK_MESSAGE_QUESTION,
+                                   GTK_BUTTONS_YES_NO,
+                                   _("The next unread message is in %s"),
+                                   mailbox->name);
+#if HAVE_MACOSX_DESKTOP
+        libbalsa_macosx_menu_for_parent(dialog, GTK_WINDOW(window));
+#endif
+        gtk_message_dialog_format_secondary_text
+            (GTK_MESSAGE_DIALOG(dialog),
+             _("Do you want to select %s?"), mailbox->name);
+        gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+                                        GTK_RESPONSE_YES);
+        response = gtk_dialog_run(GTK_DIALOG(dialog));
+        gtk_widget_destroy(dialog);
+        if (response != GTK_RESPONSE_YES)
+            return FALSE;
+    }
+
+    balsa_mblist_open_mailbox(mailbox);
+    index = balsa_find_index_by_mailbox(mailbox);
+    if (index)
+        balsa_index_select_next_unread(index);
+    else
+        g_object_set_data(G_OBJECT(mailbox),
+                          BALSA_INDEX_VIEW_ON_OPEN, GINT_TO_POINTER(TRUE));
+    return TRUE;
+}
diff --git a/src/main-window.h b/src/main-window.h
index 8de7e36..a0a2f0b 100644
--- a/src/main-window.h
+++ b/src/main-window.h
@@ -58,7 +58,7 @@ typedef enum {
 
 
 struct _BalsaWindow {
-    GtkWindow window;
+    GtkApplicationWindow window;
 
     GtkWidget *toolbar;
     GtkWidget *sos_bar;
@@ -78,12 +78,6 @@ struct _BalsaWindow {
 
     guint set_message_id;
 
-    GtkActionGroup *action_group;
-    GtkActionGroup *mailbox_action_group;
-    GtkActionGroup *message_action_group;
-    GtkActionGroup *current_message_action_group;
-    GtkActionGroup *modify_message_action_group;
-
     /* Progress bar stuff: */
     BalsaWindowProgress progress_type;
     guint activity_handler;
@@ -102,7 +96,7 @@ struct _BalsaWindow {
 };
 
 struct _BalsaWindowClass {
-    GtkWindowClass parent_class;
+    GtkApplicationWindowClass parent_class;
 
     void (*open_mbnode)  (BalsaWindow * window,
                           BalsaMailboxNode * mbnode,
@@ -146,7 +140,6 @@ gboolean mail_progress_notify_cb(GIOChannel * source,
 gboolean send_progress_notify_cb(GIOChannel * source,
                                  GIOCondition condition,
                                  BalsaWindow ** window);
-void check_new_messages_cb(GtkAction * action, gpointer data);
 void check_new_messages_real(BalsaWindow * window, int type);
 void check_new_messages_count(LibBalsaMailbox * mailbox, gboolean notify);
 void empty_trash(BalsaWindow * window);
diff --git a/src/message-window.c b/src/message-window.c
index 7ecb499..e97dada 100644
--- a/src/message-window.c
+++ b/src/message-window.c
@@ -582,7 +582,7 @@ message_window_new(LibBalsaMailbox * mailbox, guint msgno)
     gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
 #endif
 
-    mw->toolbar = balsa_toolbar_new(model, ui_manager);
+    mw->toolbar = balsa_toolbar_new(model, G_OBJECT(ui_manager));
     gtk_box_pack_start(GTK_BOX(vbox), mw->toolbar, FALSE, FALSE, 0);
 
     /* Now that we have installed the menubar and toolbar, we no longer
diff --git a/src/sendmsg-window.c b/src/sendmsg-window.c
index b0afb7a..17224d7 100644
--- a/src/sendmsg-window.c
+++ b/src/sendmsg-window.c
@@ -4664,7 +4664,7 @@ sendmsg_window_new()
     gtk_box_pack_start(GTK_BOX(main_box), menubar, FALSE, FALSE, 0);
 #endif
 
-    bsmsg->toolbar = balsa_toolbar_new(model, ui_manager);
+    bsmsg->toolbar = balsa_toolbar_new(model, G_OBJECT(ui_manager));
     gtk_box_pack_start(GTK_BOX(main_box), bsmsg->toolbar,
                        FALSE, FALSE, 0);
 
diff --git a/src/toolbar-factory.c b/src/toolbar-factory.c
index 680183c..bb03cdf 100644
--- a/src/toolbar-factory.c
+++ b/src/toolbar-factory.c
@@ -329,6 +329,19 @@ tm_add_action(BalsaToolbarModel * model, const gchar * stock_id,
 }
 
 void
+balsa_toolbar_model_add_entries(BalsaToolbarModel       * model,
+                                const BalsaToolbarEntry * entries,
+                                guint                     n_entries)
+{
+    guint i;
+
+    for (i = 0; i < n_entries; i++) {
+        const BalsaToolbarEntry *entry = &entries[i];
+        tm_add_action(model, entry->icon, entry->action);
+    }
+}
+
+void
 balsa_toolbar_model_add_actions(BalsaToolbarModel * model,
                                 const GtkActionEntry * entries,
                                 guint n_entries)
@@ -412,12 +425,7 @@ tm_has_second_line(BalsaToolbarModel * model)
         const gchar *icon = list->data;
         gint button = get_toolbar_button_index(icon);
 
-        if (button < 0) {
-            g_warning("button '%s' not found. ABORT!\n", icon);
-            continue;
-        }
-
-        if (strchr(balsa_toolbar_button_text(button), '\n'))
+        if (button >= 0 && strchr(balsa_toolbar_button_text(button), '\n'))
             return TRUE;
     }
 
@@ -566,7 +574,15 @@ tm_set_style(GtkWidget * toolbar, BalsaToolbarModel * model)
 /* Update a real toolbar when the model has changed.
  */
 static void
-tm_changed_cb(BalsaToolbarModel * model, GtkUIManager * ui_manager)
+tm_changed_cb(BalsaToolbarModel * model, GtkWidget * toolbar)
+{
+    tm_set_style(toolbar, model);
+
+    tm_save_model(model);
+}
+
+static void
+tm_changed_old_cb(BalsaToolbarModel * model, GtkUIManager * ui_manager)
 {
     GArray *merge_ids =
         g_object_get_data(G_OBJECT(ui_manager), BALSA_TOOLBAR_MERGE_IDS);
@@ -589,16 +605,16 @@ tm_changed_cb(BalsaToolbarModel * model, GtkUIManager * ui_manager)
 
 typedef struct {
     BalsaToolbarModel *model;
-    GtkUIManager      *ui_manager;
+    GObject           *object;
     GtkWidget         *menu;
 } toolbar_info;
 
 static void
 tm_toolbar_weak_notify(toolbar_info * info, GtkWidget * toolbar)
 {
-    g_signal_handlers_disconnect_by_func(info->model, tm_changed_cb,
-                                         info->ui_manager);
-    g_object_unref(info->ui_manager);
+    g_signal_handlers_disconnect_by_func(info->model, tm_changed_old_cb,
+                                         info->object);
+    g_object_unref(info->object);
     g_free(info);
 }
 
@@ -815,27 +831,85 @@ tm_popup_menu_cb(GtkWidget * toolbar, toolbar_info * info)
     return tm_do_popup_menu(toolbar, NULL, info);
 }
 
+static void
+tm_realize_cb(GtkWidget * toolbar, BalsaToolbarModel * model)
+{
+    tm_set_style(toolbar, model);
+}
+
 GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model,
-                             GtkUIManager * ui_manager)
+                   /* FIXME: GActionMap        * action_map */
+                             GObject * object)
 {
     GtkWidget *toolbar;
     toolbar_info *info;
-    GArray *merge_ids = g_array_new(FALSE, FALSE, sizeof(guint));
-
-    g_object_set_data_full(G_OBJECT(ui_manager), BALSA_TOOLBAR_MERGE_IDS,
-                           merge_ids, (GDestroyNotify) bt_free_merge_ids);
-
-    tm_populate(model, ui_manager, merge_ids);
-    g_signal_connect(model, "changed", G_CALLBACK(tm_changed_cb),
-                     ui_manager);
 
     info = g_new(toolbar_info, 1);
     info->model = model;
-    info->ui_manager = g_object_ref(ui_manager);
+    info->object = g_object_ref(object);
     info->menu = NULL;
 
-    toolbar = gtk_ui_manager_get_widget(ui_manager, "/Toolbar");
-    tm_set_style(toolbar, model);
+    if (GTK_IS_UI_MANAGER(object)) {
+        GtkUIManager *ui_manager = GTK_UI_MANAGER(object);
+        GArray *merge_ids = g_array_new(FALSE, FALSE, sizeof(guint));
+
+        g_object_set_data_full(G_OBJECT(ui_manager), BALSA_TOOLBAR_MERGE_IDS,
+                               merge_ids, (GDestroyNotify) bt_free_merge_ids);
+
+        tm_populate(model, ui_manager, merge_ids);
+        g_signal_connect(model, "changed", G_CALLBACK(tm_changed_old_cb),
+                         ui_manager);
+
+        toolbar = gtk_ui_manager_get_widget(ui_manager, "/Toolbar");
+    } else {
+        GActionMap *action_map = G_ACTION_MAP(object);
+        gboolean style_is_both;
+        gboolean make_two_line;
+        GSList *current = balsa_toolbar_model_get_current(model);
+        GSList *l;
+
+        style_is_both = (model->style == GTK_TOOLBAR_BOTH
+                         || (model->style == (GtkToolbarStyle) -1
+                             && tm_default_style() == GTK_TOOLBAR_BOTH));
+        make_two_line = style_is_both && tm_has_second_line(model);
+
+        toolbar = gtk_toolbar_new();
+        for (l = current; l; l = l->next) {
+            gchar *action_name, *icon_name;
+            GtkToolItem *item;
+
+            action_name = l->data;
+            l = l->next;
+            icon_name = l->data;
+
+            if (!*action_name) {
+                item = gtk_separator_tool_item_new();
+            } else {
+                GtkWidget *icon;
+                GAction *action;
+                gchar *prefixed_action;
+
+                icon = gtk_image_new_from_icon_name
+                    (icon_name, GTK_ICON_SIZE_SMALL_TOOLBAR);
+                item = gtk_tool_button_new(icon, action_name);
+                tm_set_tool_item_label(GTK_TOOL_ITEM(item), icon_name,
+                                       make_two_line);
+
+                action =
+                    g_action_map_lookup_action(action_map, action_name);
+                prefixed_action =
+                    g_strconcat(action ? "win." : "app.", action_name,
+                                NULL);
+                gtk_actionable_set_action_name(GTK_ACTIONABLE(item),
+                                               prefixed_action);
+                g_free(prefixed_action);
+            }
+            gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+        }
+        g_signal_connect(model, "changed", G_CALLBACK(tm_changed_cb),
+                         toolbar);
+    }
+    g_signal_connect(toolbar, "realize", G_CALLBACK(tm_realize_cb), model);
     g_object_weak_ref(G_OBJECT(toolbar),
                       (GWeakNotify) tm_toolbar_weak_notify, info);
 
@@ -844,5 +918,7 @@ GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model,
     g_signal_connect(toolbar, "popup-menu", G_CALLBACK(tm_popup_menu_cb),
                      info);
 
+    gtk_widget_show_all(toolbar);
+
     return toolbar;
 }
diff --git a/src/toolbar-factory.h b/src/toolbar-factory.h
index 3fd10cf..286626e 100644
--- a/src/toolbar-factory.h
+++ b/src/toolbar-factory.h
@@ -58,6 +58,15 @@ typedef struct t_button_data {
 extern button_data toolbar_buttons[];
 extern const int toolbar_button_count;
 
+typedef struct {
+    const gchar *action;
+    const gchar *icon;
+} BalsaToolbarEntry;
+
+void balsa_toolbar_model_add_entries(BalsaToolbarModel       * model,
+                                     const BalsaToolbarEntry * entries,
+                                     guint                     n_entries);
+
 typedef enum {
     BALSA_TOOLBAR_TYPE_MAIN_WINDOW,
     BALSA_TOOLBAR_TYPE_COMPOSE_WINDOW,
@@ -91,7 +100,6 @@ void balsa_toolbar_model_clear(BalsaToolbarModel * model);
 void balsa_toolbar_model_changed(BalsaToolbarModel * model);
 
 /* BalsaToolbar */
-GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model,
-                             GtkUIManager * ui_manager);
+GtkWidget *balsa_toolbar_new(BalsaToolbarModel * model, GObject * object);
 
 #endif
diff --git a/src/toolbar-prefs.c b/src/toolbar-prefs.c
index 866eb12..85774ee 100644
--- a/src/toolbar-prefs.c
+++ b/src/toolbar-prefs.c
@@ -153,10 +153,14 @@ customize_dialog_cb(GtkWidget * widget, gpointer data)
 
     /* The order of pages must be consistent with the BalsaToolbarType
      * enum. */
+#if 0
     model = balsa_window_get_toolbar_model();
     ui_manager = balsa_window_ui_manager_new(NULL);
     child = create_toolbar_page(model, ui_manager);
     g_object_unref(ui_manager);
+#else
+    child = gtk_label_new("Sorry, this toolbar cannot be edited yet.");
+#endif
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child,
                              gtk_label_new(_("Main window")));
 
@@ -406,7 +410,7 @@ create_toolbar_page(BalsaToolbarModel * model, GtkUIManager * ui_manager)
                                       -1, NULL);
 
     /* The preview is an actual, fully functional toolbar */
-    page->toolbar = balsa_toolbar_new(model, ui_manager);
+    page->toolbar = balsa_toolbar_new(model, G_OBJECT(ui_manager));
     gtk_widget_set_sensitive(page->toolbar, FALSE);
 
     /* embedded in a scrolled_window */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]