[balsa] Port preferences window from notebook to Stack



commit 5ba0a4264b56b73ee12797cd6c2fd26c0678f3f3
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Wed May 31 20:06:12 2017 -0400

    Port preferences window from notebook to Stack
    
        * src/pref-manager.c (pm_combo_box_info_free), (pm_combo_box_new),
        (pm_combo_box_set_level), (pm_combo_box_get_level),
        (pm_selection_changed), (destroy_pref_window_cb),
        (update_view_defaults), (check_font_button), (apply_prefs),
        (set_prefs), (update_address_books), (add_other_server),
        (add_button_to_box), (add_show_menu), (create_pref_option_menu),
        (create_layout_types_menu), (create_action_after_move_menu),
        (balsa_help_pbox_display), (create_information_message_menu),
        (create_mdn_reply_menu), (update_smtp_servers), (pm_grid_new),
        (pm_grid_attach), (pm_group_label), (pm_grid_attach_check),
        (pm_grid_attach_label), (pm_grid_attach_pref_menu),
        (pm_grid_attach_entry), (pm_grid_attach_color_box),
        (font_button_check_font_size), (pm_grid_attach_font_button),
        (pm_grid_attach_information_menu), (properties_modified_cb),
        (server_edit_cb), (smtp_server_update), (smtp_server_add_cb),
        (smtp_server_edit_cb), (smtp_server_del_cb), (smtp_server_changed),
        (address_book_change), (address_book_edit_cb),
        (address_book_set_default_cb), (add_menu_cb),
        (address_book_delete_cb), (pop3_add_cb), (server_add_menu_widget),
        (server_del_cb), (timer_modified_cb), (browse_modified_cb),
        (mark_quoted_modified_cb), (wrap_modified_cb),
        (pgdown_modified_cb), (option_menu_cb),
        (mailbox_close_timer_modified_cb), (filter_modified_cb),
        (expunge_on_close_cb), (expunge_auto_cb), (imap_toggled_cb),
        (convert_8bit_cb), (use_system_fonts_cb), (font_modified_cb),
        (default_font_size_cb), (response_cb),
        (pm_grid_add_main_window_group), (pm_grid_add_threading_group),
        (pm_grid_add_progress_group), (pm_append_page),
        (pm_mailserver_page), (pm_incoming_page), (pm_outgoing_page),
        (pm_display_page), (pm_threading_page), (pm_message_page),
        (pm_colors_page), (pm_format_page), (pm_status_messages_page),
        (create_address_book_page), (pm_spelling_page), (pm_startup_page),
        (pm_misc_page), (create_mail_options_section),
        (create_display_section), (open_preferences_manager_idle),
        (open_preferences_manager), (update_mail_servers): replace
        mutiple notebooks by a single stack; refactor code into groups
        of options, pages of one or more groups, and sections where
        multiple pages are related.

 ChangeLog          |   43 +
 src/pref-manager.c | 2624 +++++++++++++++++++++++++---------------------------
 2 files changed, 1327 insertions(+), 1340 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 984500a..75d5efc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2017-05-31  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Port preferences window from GtkNotebook to GtkStack
+
+       * src/pref-manager.c (pm_combo_box_info_free), (pm_combo_box_new),
+       (pm_combo_box_set_level), (pm_combo_box_get_level),
+       (pm_selection_changed), (destroy_pref_window_cb),
+       (update_view_defaults), (check_font_button), (apply_prefs),
+       (set_prefs), (update_address_books), (add_other_server),
+       (add_button_to_box), (add_show_menu), (create_pref_option_menu),
+       (create_layout_types_menu), (create_action_after_move_menu),
+       (balsa_help_pbox_display), (create_information_message_menu),
+       (create_mdn_reply_menu), (update_smtp_servers), (pm_grid_new),
+       (pm_grid_attach), (pm_group_label), (pm_grid_attach_check),
+       (pm_grid_attach_label), (pm_grid_attach_pref_menu),
+       (pm_grid_attach_entry), (pm_grid_attach_color_box),
+       (font_button_check_font_size), (pm_grid_attach_font_button),
+       (pm_grid_attach_information_menu), (properties_modified_cb),
+       (server_edit_cb), (smtp_server_update), (smtp_server_add_cb),
+       (smtp_server_edit_cb), (smtp_server_del_cb), (smtp_server_changed),
+       (address_book_change), (address_book_edit_cb),
+       (address_book_set_default_cb), (add_menu_cb),
+       (address_book_delete_cb), (pop3_add_cb), (server_add_menu_widget),
+       (server_del_cb), (timer_modified_cb), (browse_modified_cb),
+       (mark_quoted_modified_cb), (wrap_modified_cb),
+       (pgdown_modified_cb), (option_menu_cb),
+       (mailbox_close_timer_modified_cb), (filter_modified_cb),
+       (expunge_on_close_cb), (expunge_auto_cb), (imap_toggled_cb),
+       (convert_8bit_cb), (use_system_fonts_cb), (font_modified_cb),
+       (default_font_size_cb), (response_cb),
+       (pm_grid_add_main_window_group), (pm_grid_add_threading_group),
+       (pm_grid_add_progress_group), (pm_append_page),
+       (pm_mailserver_page), (pm_incoming_page), (pm_outgoing_page),
+       (pm_display_page), (pm_threading_page), (pm_message_page),
+       (pm_colors_page), (pm_format_page), (pm_status_messages_page),
+       (create_address_book_page), (pm_spelling_page), (pm_startup_page),
+       (pm_misc_page), (create_mail_options_section),
+       (create_display_section), (open_preferences_manager_idle),
+       (open_preferences_manager), (update_mail_servers): replace
+       mutiple notebooks by a single stack; refactor code into groups
+       of options, pages of one or more groups, and sections where
+       multiple pages are related.
+
 2017-05-30  Peter Bloomfield  <pbloomfield bellsouth net>
 
        Port preferences window to GtkGrid
diff --git a/src/pref-manager.c b/src/pref-manager.c
index 3db41c4..6c6988f 100644
--- a/src/pref-manager.c
+++ b/src/pref-manager.c
@@ -170,11 +170,11 @@ typedef struct _PropertyUI {
     GtkRadioButton *convert_unknown_8bit[NUM_CONVERT_8BIT_MODES];
     GtkWidget *convert_unknown_8bit_codeset;
 
-#if !HAVE_GTKSPELL
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
     /* spell checking */
     GtkWidget *spell_check_sig;
     GtkWidget *spell_check_quoted;
-#endif                          /* HAVE_GTKSPELL */
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
     /* folder scanning */
     GtkWidget *local_scan_depth;
@@ -187,118 +187,16 @@ static PropertyUI *pui = NULL;
 static GtkWidget *property_box;
 static gboolean already_open;
 
-    /* Mail Options page */
-static GtkWidget *create_mail_options_page(GtkTreeStore * store);
-
-static GtkWidget *mailserver_subpage(void);
-static GtkWidget *incoming_subpage(void);
-static GtkWidget *outgoing_subpage(void);
-    /* End of Mail Options page */
-
-    /* Display Options page */
-static GtkWidget *create_display_page(GtkTreeStore * store);
-
-static GtkWidget *display_subpage(void);
-static GtkWidget *threading_subpage(void);
-static GtkWidget *message_subpage(void);
-static GtkWidget *colors_subpage(void);
-static GtkWidget *format_subpage(void);
-static GtkWidget *status_messages_subpage(void);
-    /* End of Display Options page */
-
-    /* Address Books page */
-static GtkWidget *create_address_book_page(GtkTreeStore * store);
-    /* End of Address Books page */
-
-    /* Startup page */
-static GtkWidget *create_startup_page(GtkTreeStore * store);
-    /* End of Startup page */
-
-    /* Misc page */
-static GtkWidget *create_misc_page(GtkTreeStore * store);
-    /* End of Misc page */
-
-#if !HAVE_GTKSPELL
-    /* Spelling page */
-static GtkWidget *create_spelling_page(GtkTreeStore * store);
-#endif                          /* HAVE_GTKSPELL */
-
-    /* general helpers */
-static void add_show_menu(const char *label, gint level, GtkWidget * menu);
-static GtkWidget *create_pref_option_menu(const gchar * names[], gint size,
-                                          gint * index);
-
-    /* page and group object methods */
-static void pm_append_page(GtkWidget * notebook, GtkWidget * widget,
-                           const gchar * text, GtkTreeStore * store,
-                           GtkTreeIter * parent_iter);
-
     /* combo boxes */
 struct pm_combo_box_info {
     GSList *levels;
 };
 #define PM_COMBO_BOX_INFO "balsa-pref-manager-combo-box-info"
 
-static GtkWidget *pm_combo_box_new(void);
-static void pm_combo_box_set_level(GtkWidget * combo_box, gint level);
-static gint pm_combo_box_get_level(GtkWidget * combo_box);
-
-    /* special helpers */
-static GtkWidget *create_layout_types_menu(void);
-static GtkWidget *create_action_after_move_menu(void);
-static GtkWidget *create_information_message_menu(void);
-static GtkWidget *create_mdn_reply_menu(void);
-static void balsa_help_pbox_display(void);
-
-    /* updaters */
-static void set_prefs(void);
-static void apply_prefs(GtkDialog * dialog);
-void update_mail_servers(void); /* public; in pref-manager.h */
-static void smtp_server_update(LibBalsaSmtpServer *, GtkResponseType,
-                              const gchar *);
-static void update_smtp_servers(void);
-
     /* callbacks */
-static void response_cb(GtkDialog * dialog, gint response, gpointer data);
-static void destroy_pref_window_cb(void);
-static void update_address_books(void);
 static void properties_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-
-static void server_edit_cb(GtkTreeView * tree_view);
-static void pop3_add_cb(void);
-static void add_menu_cb(GtkWidget * menu, GtkWidget * widget);
-static void server_del_cb(GtkTreeView * tree_view);
-
-static void smtp_server_edit_cb(GtkTreeView * tree_view);
-static void smtp_server_add_cb(void);
-static void smtp_server_del_cb(GtkTreeView * tree_view);
-static void smtp_server_changed (GtkTreeSelection * selection,
-                                gpointer user_data);
-
-static void address_book_edit_cb(GtkTreeView * tree_view);
-static void address_book_delete_cb(GtkTreeView * tree_view);
-static void address_book_set_default_cb(GtkTreeView * tree_view);
-static void timer_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-static void mailbox_close_timer_modified_cb(GtkWidget * widget,
-                                            GtkWidget * pbox);
-static void browse_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-static void mark_quoted_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-static void wrap_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-
-static void use_system_fonts_cb(GtkWidget * widget, GtkWidget * pbox);
-static void font_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-static void default_font_size_cb(GtkWidget * widget, GtkWidget * pbox);
-
-static void pgdown_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-
 static void option_menu_cb(GtkMenuItem * menuitem, gpointer data);
-static void imap_toggled_cb(GtkWidget * widget, GtkWidget * pbox);
-
-static void convert_8bit_cb(GtkWidget * widget, GtkWidget * pbox);
-
-static void filter_modified_cb(GtkWidget * widget, GtkWidget * pbox);
-static void expunge_on_close_cb(GtkWidget * widget, GtkWidget * pbox);
-static void expunge_auto_cb(GtkWidget * widget, GtkWidget * pbox);
+static void address_book_change(LibBalsaAddressBook * address_book, gboolean append);
 
 guint pwindow_type[NUM_PWINDOW_MODES] = {
     WHILERETR,
@@ -327,371 +225,84 @@ const gchar *threading_type_label[NUM_THREADING_STYLES] = {
     N_("JWZ")
 };
 
-    /* and now the important stuff: */
-static gboolean
-open_preferences_manager_idle(void)
-{
-    gchar *name;
+/* combo boxes */
 
-    gdk_threads_enter();
+static void
+pm_combo_box_info_free(struct pm_combo_box_info * info)
+{
+    g_slist_free(info->levels);
+    g_free(info);
+}
 
-    if (pui == NULL) {
-        gdk_threads_leave();
-        return FALSE;
-    }
+static GtkWidget *
+pm_combo_box_new(void)
+{
+    GtkWidget *combo_box = gtk_combo_box_text_new();
+    struct pm_combo_box_info *info = g_new0(struct pm_combo_box_info, 1);
 
-    name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER
-                                         (pui->mail_directory));
-    if (!name || strcmp(name, balsa_app.local_mail_directory) != 0) {
-        /* Chooser still hasn't been initialized. */
-        g_free(name);
-        gdk_threads_leave();
-        return TRUE;
-    }
-    g_free(name);
+    gtk_widget_set_hexpand(combo_box, TRUE);
 
-    g_signal_connect(pui->mail_directory, "selection-changed",
+    g_object_set_data_full(G_OBJECT(combo_box), PM_COMBO_BOX_INFO, info,
+                           (GDestroyNotify) pm_combo_box_info_free);
+    g_signal_connect(G_OBJECT(combo_box), "changed",
                      G_CALLBACK(properties_modified_cb), property_box);
 
-    gdk_threads_leave();
-    return FALSE;
-}                               /* open_preferences_manager_idle */
+    return combo_box;
+}
+
+static void
+pm_combo_box_set_level(GtkWidget * combo_box, gint level)
+{
+    struct pm_combo_box_info *info =
+        g_object_get_data(G_OBJECT(combo_box), PM_COMBO_BOX_INFO);
+    GSList *list;
+    guint i;
+
+    for (list = info->levels, i = 0; list; list = list->next, ++i)
+       if (GPOINTER_TO_INT(list->data) == level) {
+           gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), i);
+           break;
+       }
+}
+
+static gint
+pm_combo_box_get_level(GtkWidget * combo_box)
+{
+    struct pm_combo_box_info *info =
+        g_object_get_data(G_OBJECT(combo_box), PM_COMBO_BOX_INFO);
+    gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
+
+    return GPOINTER_TO_INT(g_slist_nth_data(info->levels, active));
+}
+
+    /* and now the important stuff: */
 
 enum {
     PM_TEXT_COL,
     PM_HELP_COL,
-    PM_NOTEBOOK_COL,
     PM_CHILD_COL,
-    PM_PAGE_COL,
     PM_NUM_COLS
 };
 
 static void
-pm_selection_changed(GtkTreeSelection * selection, gpointer data)
+pm_selection_changed(GtkTreeSelection * selection, gpointer user_data)
 {
+    GtkStack *stack = user_data;
     GtkTreeModel *model;
-    GtkTreeIter iter, child;
-    GtkNotebook *notebook;
-    guint page;
+    GtkTreeIter iter;
+    GtkWidget *child;
 
     if (!gtk_tree_selection_get_selected(selection, &model, &iter))
         return;
 
     gtk_tree_model_get(model, &iter,
-                       PM_CHILD_COL, &notebook,
+                       PM_CHILD_COL, &child,
                        -1);
-    if (notebook) {
-        gtk_notebook_set_current_page(notebook, 0);
-        g_object_unref(notebook);
-    }
-
-    do {
-        gtk_tree_model_get(model, &iter,
-                           PM_NOTEBOOK_COL, &notebook,
-                           PM_PAGE_COL, &page,
-                           -1);
-        if (notebook) {
-            gtk_notebook_set_current_page(notebook, page);
-            g_object_unref(notebook);
-        }
-        child = iter;
-    } while (gtk_tree_model_iter_parent(model, &iter, &child));
-}
-
-void
-open_preferences_manager(GtkWidget * widget, gpointer data)
-{
-    GtkWidget *hbox;
-    GtkTreeStore *store;
-    GtkWidget *view;
-    GtkTreeSelection * selection;
-    GtkWidget *notebook;
-    GtkWidget *active_win = data;
-    gint i;
-    GtkCellRenderer *renderer;
-    GtkTreeViewColumn *column;
-
-    /* only one preferences manager window */
-    if (already_open) {
-        gtk_window_present(GTK_WINDOW(property_box));
-        return;
-    }
-
-    pui = g_malloc(sizeof(PropertyUI));
-
-    property_box =              /* must NOT be modal */
-        gtk_dialog_new_with_buttons(_("Balsa Preferences"),
-                                    GTK_WINDOW(active_win),
-                                    GTK_DIALOG_DESTROY_WITH_PARENT |
-                                    libbalsa_dialog_flags(),
-                                    _("_OK"), GTK_RESPONSE_OK,
-                                    _("_Apply"), GTK_RESPONSE_APPLY,
-                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                    _("_Help"), GTK_RESPONSE_HELP,
-                                    NULL);
-#if HAVE_MACOSX_DESKTOP
-    libbalsa_macosx_menu_for_parent(property_box, GTK_WINDOW(active_win));
-#endif
-
-    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
-    gtk_container_add(GTK_CONTAINER
-                      (gtk_dialog_get_content_area
-                       (GTK_DIALOG(property_box))), hbox);
-
-    store = gtk_tree_store_new(PM_NUM_COLS,
-                               G_TYPE_STRING,   /* PM_TEXT_COL     */
-                               G_TYPE_STRING,   /* PM_HELP_COL     */
-                               GTK_TYPE_WIDGET, /* PM_NOTEBOOK_COL */
-                               GTK_TYPE_WIDGET, /* PM_CHILD_COL    */
-                               G_TYPE_INT       /* PM_PAGE_COL     */
-            );
-    pui->view = view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
-    gtk_container_add(GTK_CONTAINER(hbox), view);
-    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
-
-    renderer = gtk_cell_renderer_text_new();
-    column =
-        gtk_tree_view_column_new_with_attributes(NULL, renderer,
-                                                 "text", PM_TEXT_COL,
-                                                 NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
-
-    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
-    g_signal_connect(selection, "changed",
-                     G_CALLBACK(pm_selection_changed), NULL);
-
-    notebook = gtk_notebook_new();
-    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
-    gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
-    gtk_container_add(GTK_CONTAINER(hbox), notebook);
-    g_object_set_data(G_OBJECT(property_box), "notebook", notebook);
-
-    already_open = TRUE;
-
-    gtk_window_set_resizable(GTK_WINDOW(property_box), FALSE);
-    g_object_set_data(G_OBJECT(property_box), "balsawindow", active_win);
-
-    /* Create the pages */
-    pm_append_page(notebook, create_mail_options_page(store),
-                   N_("Mail options"), store, NULL);
-    pm_append_page(notebook, create_display_page(store),
-                   N_("Display options"), store, NULL);
-    pm_append_page(notebook, create_address_book_page(store),
-                   N_("Address books"), store, NULL);
-
-#if !HAVE_GTKSPELL
-    pm_append_page(notebook, create_spelling_page(store),
-                   N_("Spelling"), store, NULL);
-#endif                          /* HAVE_GTKSPELL */
-
-    pm_append_page(notebook, create_startup_page(store),
-                   N_("Start-up"), store, NULL);
-    pm_append_page(notebook, create_misc_page(store),
-                   N_("Miscellaneous"), store, NULL);
-
-    gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
-
-    set_prefs();
-    /* Now that all the prefs have been set, we must desensitize the
-     * buttons. */
-    gtk_dialog_set_response_sensitive(GTK_DIALOG(property_box),
-                                      GTK_RESPONSE_OK, FALSE);
-    gtk_dialog_set_response_sensitive(GTK_DIALOG(property_box),
-                                      GTK_RESPONSE_APPLY, FALSE);
-
-    for (i = 0; i < NUM_PWINDOW_MODES; i++) {
-        g_signal_connect(G_OBJECT(pui->pwindow_type[i]), "clicked",
-                         G_CALLBACK(properties_modified_cb), property_box);
-    }
-
-    g_signal_connect(G_OBJECT(pui->previewpane), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->layout_type), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->view_message_on_open), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->ask_before_select), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->pgdownmod), "toggled",
-                     G_CALLBACK(pgdown_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->pgdown_percent), "changed",
-                     G_CALLBACK(pgdown_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->debug), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->mblist_show_mb_content_info), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-#if !HAVE_GTKSPELL
-    g_signal_connect(G_OBJECT(pui->spell_check_sig), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->spell_check_quoted), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-#endif                          /* HAVE_GTKSPELL */
-
-    /* Connect signal in an idle handler, after the file chooser has
-     * been initialized. */
-    g_idle_add_full(G_PRIORITY_LOW,
-                    (GSourceFunc) open_preferences_manager_idle,
-                    NULL, NULL);
-    g_signal_connect(G_OBJECT(pui->check_mail_auto), "toggled",
-                     G_CALLBACK(timer_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->check_mail_minutes), "changed",
-                     G_CALLBACK(timer_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->quiet_background_check), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->msg_size_limit), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->check_imap), "toggled",
-                     G_CALLBACK(imap_toggled_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->check_imap_inbox), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->notify_new_mail_dialog), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->notify_new_mail_sound), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->notify_new_mail_icon), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->close_mailbox_auto), "toggled",
-                     G_CALLBACK(mailbox_close_timer_modified_cb),
-                     property_box);
-    g_signal_connect(G_OBJECT(pui->close_mailbox_minutes), "changed",
-                     G_CALLBACK(mailbox_close_timer_modified_cb),
-                     property_box);
-
-    g_signal_connect(G_OBJECT(pui->hide_deleted), "toggled",
-                     G_CALLBACK(filter_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->expunge_on_close), "toggled",
-                     G_CALLBACK(expunge_on_close_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->expunge_auto), "toggled",
-                     G_CALLBACK(expunge_auto_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->expunge_minutes), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->browse_wrap), "toggled",
-                     G_CALLBACK(browse_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->browse_wrap_length), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->wordwrap), "toggled",
-                     G_CALLBACK(wrap_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->wraplength), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->always_queue_sent_mail), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->copy_to_sentbox), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->autoquote), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->reply_include_html_parts), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->forward_attached), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* external editor */
-    g_signal_connect(G_OBJECT(pui->edit_headers), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* arp */
-    g_signal_connect(G_OBJECT(pui->quote_str), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->mark_quoted), "toggled",
-                     G_CALLBACK(mark_quoted_modified_cb),
-                     property_box);
-    g_signal_connect(G_OBJECT(pui->quote_pattern), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* multipart/alternative */
-    g_signal_connect(G_OBJECT(pui->display_alt_plain), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* convert 8-bit text with no charset header */
-    g_signal_connect(G_OBJECT(pui->convert_unknown_8bit_codeset),
-                     "changed", G_CALLBACK(properties_modified_cb),
-                     property_box);
-
-    /* message font */
-    g_signal_connect(G_OBJECT(pui->use_system_fonts), "toggled",
-                     G_CALLBACK(use_system_fonts_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->message_font_button), "font-set",
-                     G_CALLBACK(font_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->subject_font_button), "font-set",
-                     G_CALLBACK(font_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->use_default_font_size), "toggled",
-                     G_CALLBACK(default_font_size_cb), property_box);
-
-
-    g_signal_connect(G_OBJECT(pui->open_inbox_upon_startup), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->check_mail_upon_startup), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->remember_open_mboxes), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->local_scan_depth), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-    g_signal_connect(G_OBJECT(pui->imap_scan_depth), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->empty_trash), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* threading */
-    g_signal_connect(G_OBJECT(pui->tree_expand_check), "toggled",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-
-    /* Date format */
-    g_signal_connect(G_OBJECT(pui->date_format), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* Selected headers */
-    g_signal_connect(G_OBJECT(pui->selected_headers), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* Colour */
-    for (i = 0; i < MAX_QUOTED_COLOR; i++)
-        g_signal_connect(G_OBJECT(pui->quoted_color[i]), "released",
-                         G_CALLBACK(properties_modified_cb), property_box);
-
-    g_signal_connect(G_OBJECT(pui->url_color), "released",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    /* handling of message parts with 8-bit chars without codeset headers */
-    for (i = 0; i < NUM_CONVERT_8BIT_MODES; i++)
-        g_signal_connect(G_OBJECT(pui->convert_unknown_8bit[i]), "toggled",
-                         G_CALLBACK(convert_8bit_cb), property_box);
-
-    /* Gnome Property Box Signals */
-    g_signal_connect(G_OBJECT(property_box), "response",
-                     G_CALLBACK(response_cb), NULL);
-
-    gtk_widget_show_all(GTK_WIDGET(property_box));
-
-}                               /* open_preferences_manager */
-
-static void
-response_cb(GtkDialog * dialog, gint response, gpointer data)
-{
-    switch (response) {
-    case GTK_RESPONSE_APPLY:
-        apply_prefs(dialog);
-        break;
-    case GTK_RESPONSE_HELP:
-        balsa_help_pbox_display();
-        break;
-    case GTK_RESPONSE_OK:
-        apply_prefs(dialog);
-        /* and fall through to... */
-    default:
-        destroy_pref_window_cb();
-        gtk_widget_destroy(GTK_WIDGET(dialog));
+    if (child != NULL) {
+        gtk_stack_set_visible_child(stack, child);
+        g_object_unref(child);
+    } else {
+        g_print("%s no child\n", G_STRLOC);
     }
 }
 
@@ -961,7 +572,7 @@ apply_prefs(GtkDialog * pbox)
     balsa_app.empty_trash_on_exit =
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->empty_trash));
 
-#if !HAVE_GSPELL && !HAVE_GTKSPELL
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
     /* spell checking */
     balsa_app.check_sig =
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
@@ -969,7 +580,7 @@ apply_prefs(GtkDialog * pbox)
     balsa_app.check_quoted =
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
                                      (pui->spell_check_quoted));
-#endif                          /* HAVE_GTKSPELL */
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
     /* date format */
     g_free(balsa_app.date_string);
@@ -1033,7 +644,7 @@ apply_prefs(GtkDialog * pbox)
 /*
  * refresh data in the preferences window
  */
-void
+static void
 set_prefs(void)
 {
     unsigned i;
@@ -1203,14 +814,14 @@ set_prefs(void)
     pm_combo_box_set_level(pui->default_threading_type,
                            pui->threading_type_index);
 
-#if !HAVE_GSPELL && !HAVE_GTKSPELL
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
     /* spelling */
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->spell_check_sig),
                                  balsa_app.check_sig);
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
                                  (pui->spell_check_quoted),
                                  balsa_app.check_quoted);
-#endif                          /* HAVE_GTKSPELL */
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
 
     /* date format */
@@ -1369,79 +980,190 @@ add_other_server(BalsaMailboxNode * mbnode, GtkTreeModel * model)
     }
 }
 
-/* update_mail_servers:
-   update mail server list in the preferences window.
-   NOTE: it can be called even when the preferences window is closed (via
-   mailbox context menu) - and it should check for it.
- */
-void
-update_mail_servers(void)
+/* helper functions that simplify often performed actions */
+
+static GtkWidget *
+add_button_to_box(const gchar * label, GCallback cb, gpointer cb_data,
+                  GtkWidget * box)
 {
-    GtkTreeView *tree_view;
+    GtkWidget *button = gtk_button_new_with_mnemonic(label);
+    g_signal_connect_swapped(button, "clicked", cb, cb_data);
+    gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
+
+    return button;
+}
+
+static GtkWidget * server_add_menu_widget(void);
+
+static void
+add_show_menu(const char* label, gint level, GtkWidget* menu)
+{
+    struct pm_combo_box_info *info =
+        g_object_get_data(G_OBJECT(menu), PM_COMBO_BOX_INFO);
+
+    gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menu), label);
+    info->levels = g_slist_append(info->levels, GINT_TO_POINTER(level));
+}
+
+static GtkWidget *
+create_pref_option_menu(const gchar * names[], gint size, gint * index)
+{
+    GtkWidget *combo_box;
+    gint i;
+
+    combo_box = pm_combo_box_new();
+    g_signal_connect(G_OBJECT(combo_box), "changed",
+                     G_CALLBACK(option_menu_cb), index);
+
+    for (i = 0; i < size; i++)
+       add_show_menu(_(names[i]), i, combo_box);
+
+    return combo_box;
+}
+
+static GtkWidget *
+create_layout_types_menu(void)
+{
+    GtkWidget *combo_box = pm_combo_box_new();
+    add_show_menu(_("Default layout"), LAYOUT_DEFAULT, combo_box);
+    add_show_menu(_("Wide message layout"), LAYOUT_WIDE_MSG, combo_box);
+    add_show_menu(_("Wide screen layout"), LAYOUT_WIDE_SCREEN, combo_box);
+    return combo_box;
+}
+
+static GtkWidget *
+create_action_after_move_menu(void)
+{
+    GtkWidget *combo_box = pm_combo_box_new();
+    add_show_menu(_("Show next unread message"), NEXT_UNREAD, combo_box);
+    add_show_menu(_("Show next message"), NEXT, combo_box);
+    add_show_menu(_("Close message window"), CLOSE, combo_box);
+    return combo_box;
+}
+
+static void
+balsa_help_pbox_display(void)
+{
+    GtkTreeSelection *selection;
     GtkTreeModel *model;
     GtkTreeIter iter;
-    GList *list;
-    gchar *protocol;
-    GtkTreeModel *app_model;
-    gboolean valid;
-    BalsaMailboxNode *mbnode;
+    GtkTreeIter parent;
+    gchar *text, *p;
+    GError *err = NULL;
+    gchar *uri;
+#if GTK_CHECK_VERSION(3, 22, 0)
+    GtkWidget *toplevel;
+#else /* GTK_CHECK_VERSION(3, 22, 0) */
+    GdkScreen *screen;
+#endif /* GTK_CHECK_VERSION(3, 22, 0) */
+    GString *string;
 
-    if (pui == NULL)
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pui->view));
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
         return;
 
-    tree_view = GTK_TREE_VIEW(pui->mail_servers);
-    model = gtk_tree_view_get_model(tree_view);
+    string = g_string_new("help:balsa/preferences-");
 
-    gtk_list_store_clear(GTK_LIST_STORE(model));
-    for (list = balsa_app.inbox_input; list; list = list->next) {
-        if (!(mbnode = list->data))
-            continue;
-        if (LIBBALSA_IS_MAILBOX_POP3(mbnode->mailbox))
-            protocol = "POP3";
-        else if (LIBBALSA_IS_MAILBOX_IMAP(mbnode->mailbox))
-            protocol = "IMAP";
-        else
-            protocol = _("Unknown");
+    if (gtk_tree_model_iter_parent(model, &parent, &iter)) {
+        gtk_tree_model_get(model, &parent, PM_HELP_COL, &text, -1);
+        for (p = text; *p; p++)
+            *p = (*p == ' ') ? '-' : g_ascii_tolower(*p);
+        g_string_append(string, text);
+        g_free(text);
+        g_string_append_c(string, '#');
+    }
+    gtk_tree_model_get(model, &iter, PM_HELP_COL, &text, -1);
+    for (p = text; *p; p++)
+        *p = (*p == ' ') ? '-' : g_ascii_tolower(*p);
+    g_string_append(string, text);
+    g_free(text);
 
-        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                           MS_PROT_COLUMN, protocol,
-                           MS_NAME_COLUMN, mbnode->mailbox->name,
-                           MS_DATA_COLUMN, mbnode, -1);
+    uri = g_string_free(string, FALSE);
+#if GTK_CHECK_VERSION(3, 22, 0)
+    toplevel = gtk_widget_get_toplevel(GTK_WIDGET(pui->view));
+    if (gtk_widget_is_toplevel(toplevel)) {
+        gtk_show_uri_on_window(GTK_WINDOW(toplevel), uri,
+                               gtk_get_current_event_time(), &err);
     }
-    /*
-     * add other remote servers
-     *
-     * we'll check everything at the top level in the mailbox_nodes
-     * list:
-     */
-    app_model = GTK_TREE_MODEL(balsa_app.mblist_tree_store);
-    for (valid = gtk_tree_model_get_iter_first(app_model, &iter);
-         valid; valid = gtk_tree_model_iter_next(app_model, &iter)) {
-        gtk_tree_model_get(app_model, &iter, 0, &mbnode, -1);
-        add_other_server(mbnode, model);
-        g_object_unref(mbnode);
+#else  /* GTK_CHECK_VERSION(3, 22, 0) */
+    screen = gtk_widget_get_screen(pui->view);
+    gtk_show_uri(screen, uri, gtk_get_current_event_time(), &err);
+#endif /* GTK_CHECK_VERSION(3, 22, 0) */
+    if (err) {
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+               _("Error displaying %s: %s\n"),
+               uri, err->message);
+        g_error_free(err);
     }
 
-    if (gtk_tree_model_get_iter_first(model, &iter))
-        gtk_tree_selection_select_iter(gtk_tree_view_get_selection
-                                       (tree_view), &iter);
+    g_free(uri);
 }
 
-/* helper functions that simplify often performed actions */
+static GtkWidget *
+create_information_message_menu(void)
+{
+    GtkWidget *combo_box = pm_combo_box_new();
+
+    add_show_menu(_("Show nothing"),       BALSA_INFORMATION_SHOW_NONE,
+                  combo_box);
+    add_show_menu(_("Show dialog"),        BALSA_INFORMATION_SHOW_DIALOG,
+                  combo_box);
+    add_show_menu(_("Show in list"),       BALSA_INFORMATION_SHOW_LIST,
+                  combo_box);
+    add_show_menu(_("Show in status bar"), BALSA_INFORMATION_SHOW_BAR,
+                  combo_box);
+    add_show_menu(_("Print to console"),   BALSA_INFORMATION_SHOW_STDERR,
+                  combo_box);
+
+    return combo_box;
+}
 
 static GtkWidget *
-add_button_to_box(const gchar * label, GCallback cb, gpointer cb_data,
-                  GtkWidget * box)
+create_mdn_reply_menu(void)
 {
-    GtkWidget *button = gtk_button_new_with_mnemonic(label);
-    g_signal_connect_swapped(button, "clicked", cb, cb_data);
-    gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
+    GtkWidget *combo_box = pm_combo_box_new();
 
-    return button;
+    add_show_menu(_("Never"),  BALSA_MDN_REPLY_NEVER,  combo_box);
+    add_show_menu(_("Ask me"), BALSA_MDN_REPLY_ASKME,  combo_box);
+    add_show_menu(_("Always"), BALSA_MDN_REPLY_ALWAYS, combo_box);
+
+    return combo_box;
 }
 
-static GtkWidget * server_add_menu_widget(void);
+/* Clear and populate the list. */
+static void
+update_smtp_servers(void)
+{
+    GtkTreeView *tree_view;
+    GtkTreeSelection *selection;
+    GtkTreeIter iter;
+    GtkTreePath *path = NULL;
+    GtkTreeModel *model;
+    GSList *list;
+
+    if (pui == NULL)
+        return;
+
+    tree_view = GTK_TREE_VIEW(pui->smtp_servers);
+    selection = gtk_tree_view_get_selection(tree_view);
+    if (gtk_tree_selection_get_selected(selection, &model, &iter))
+        path = gtk_tree_model_get_path(model, &iter);
+
+    gtk_list_store_clear(GTK_LIST_STORE(model));
+
+    for (list = balsa_app.smtp_servers; list; list = list->next) {
+        LibBalsaSmtpServer *smtp_server = LIBBALSA_SMTP_SERVER(list->data);
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                           0, libbalsa_smtp_server_get_name(smtp_server),
+                           1, smtp_server, -1);
+    }
+
+    if (path) {
+        gtk_tree_selection_select_path(selection, path);
+        gtk_tree_path_free(path);
+    }
+}
 
 /***************************
  *
@@ -1694,14 +1416,515 @@ pm_grid_attach_information_menu(GtkGrid     * grid,
  * End of helpers for GtkGrid pages
  */
 
-/*******************
+/*
+ * callbacks
+ */
+static void
+properties_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(pbox), GTK_RESPONSE_OK,
+                                      TRUE);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(pbox), GTK_RESPONSE_APPLY,
+                                      TRUE);
+}
+
+static void
+server_edit_cb(GtkTreeView * tree_view)
+{
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    BalsaMailboxNode *mbnode;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+       return;
+
+    gtk_tree_model_get(model, &iter, MS_DATA_COLUMN, &mbnode, -1);
+    g_return_if_fail(mbnode);
+    balsa_mailbox_node_show_prop_dialog(mbnode);
+}
+
+#define SMTP_SERVER_SECTION_PREFIX "smtp-server-"
+
+/* Callback for the server-dialog's response handler. */
+static void
+smtp_server_update(LibBalsaSmtpServer * smtp_server,
+                   GtkResponseType response, const gchar * old_name)
+{
+    gchar *group;
+    const gchar *new_name;
+
+    new_name = libbalsa_smtp_server_get_name(smtp_server);
+
+    if (old_name) {
+        /* We were editing an existing server. */
+        if (strcmp(old_name, new_name) == 0)
+           return;
+       else {
+            /* Name was changed. */
+            group =
+                g_strconcat(SMTP_SERVER_SECTION_PREFIX, old_name, NULL);
+            libbalsa_conf_remove_group(group);
+            g_free(group);
+        }
+    } else {
+        /* Populating a new server. */
+        if (response == GTK_RESPONSE_OK)
+            libbalsa_smtp_server_add_to_list(smtp_server,
+                                             &balsa_app.smtp_servers);
+        else {
+            /*  The user killed the dialog. */
+            g_object_unref(smtp_server);
+            return;
+        }
+    }
+
+    update_smtp_servers();
+
+    group = g_strconcat(SMTP_SERVER_SECTION_PREFIX, new_name, NULL);
+    libbalsa_conf_push_group(group);
+    g_free(group);
+    libbalsa_smtp_server_save_config(smtp_server);
+    libbalsa_conf_pop_group();
+}
+
+static void
+smtp_server_add_cb(void)
+{
+    LibBalsaSmtpServer *smtp_server;
+
+    smtp_server = libbalsa_smtp_server_new();
+    libbalsa_smtp_server_dialog(smtp_server,
+                                GTK_WINDOW(property_box),
+                                smtp_server_update);
+}
+
+static void
+smtp_server_edit_cb(GtkTreeView * tree_view)
+{
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    LibBalsaSmtpServer *smtp_server;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+        return;
+
+    gtk_tree_model_get(model, &iter, 1, &smtp_server, -1);
+    g_return_if_fail(smtp_server);
+    libbalsa_smtp_server_dialog(smtp_server,
+                                GTK_WINDOW(property_box),
+                                smtp_server_update);
+}
+
+static void
+smtp_server_del_cb(GtkTreeView * tree_view)
+{
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    LibBalsaSmtpServer *smtp_server;
+    gchar *group;
+
+    /* Nothing to do if no server is selected, or if it is the last one. */
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter)
+        || gtk_tree_model_iter_n_children(model, NULL) <= 1)
+        return;
+
+    gtk_tree_model_get(model, &iter, 1, &smtp_server, -1);
+    g_return_if_fail(smtp_server);
+
+    group = g_strconcat(SMTP_SERVER_SECTION_PREFIX,
+                        libbalsa_smtp_server_get_name(smtp_server), NULL);
+    libbalsa_conf_remove_group(group);
+    g_free(group);
+
+    balsa_app.smtp_servers =
+        g_slist_remove(balsa_app.smtp_servers, smtp_server);
+    g_object_unref(smtp_server);
+    update_smtp_servers();
+}
+
+/* Set sensitivity of the Modify and Delete buttons; we can edit a server
+ * only if one is selected, and we can delete one only if it is selected
+ * and it is not the last server. */
+static void
+smtp_server_changed(GtkTreeSelection * selection, gpointer user_data)
+{
+    gboolean selected;
+    GtkTreeModel *model;
+
+    selected = gtk_tree_selection_get_selected(selection, &model, NULL);
+    gtk_widget_set_sensitive(pui->smtp_server_edit_button, selected);
+    gtk_widget_set_sensitive(pui->smtp_server_del_button,
+                             selected
+                             && gtk_tree_model_iter_n_children(model,
+                                                               NULL) > 1);
+}
+
+/* Address book callbacks */
+
+static void
+address_book_change(LibBalsaAddressBook * address_book, gboolean append)
+{
+    if (append) {
+        balsa_app.address_book_list =
+            g_list_append(balsa_app.address_book_list, address_book);
+       balsa_window_update_book_menus(balsa_app.main_window);
+    }
+    config_address_book_save(address_book);
+    update_address_books();
+}
+
+static void
+address_book_edit_cb(GtkTreeView * tree_view)
+{
+    LibBalsaAddressBook *address_book;
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+       return;
+
+    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+
+    g_assert(address_book != NULL);
+
+    balsa_address_book_config_new(address_book, address_book_change,
+                                  GTK_WINDOW(property_box));
+}
+
+static void
+address_book_set_default_cb(GtkTreeView * tree_view)
+{
+    LibBalsaAddressBook *address_book;
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+       return;
+
+    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+
+    g_assert(address_book != NULL);
+    balsa_app.default_address_book = address_book;
+
+    path = gtk_tree_model_get_path(model, &iter);
+    update_address_books();
+    gtk_tree_selection_select_path(selection, path);
+    gtk_tree_path_free(path);
+}
+
+static void
+add_menu_cb(GtkWidget * menu, GtkWidget * widget)
+{
+    gtk_widget_show_all(menu);
+#if GTK_CHECK_VERSION(3, 22, 0)
+    gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(widget),
+                             GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST,
+                             NULL);
+#else                           /*GTK_CHECK_VERSION(3, 22, 0) */
+    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0,
+                   gtk_get_current_event_time());
+#endif                          /*GTK_CHECK_VERSION(3, 22, 0) */
+}
+
+static void
+address_book_delete_cb(GtkTreeView * tree_view)
+{
+    LibBalsaAddressBook *address_book;
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+       return;
+
+    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+
+    g_assert(address_book != NULL);
+
+    config_address_book_delete(address_book);
+    balsa_app.address_book_list =
+       g_list_remove(balsa_app.address_book_list, address_book);
+    balsa_window_update_book_menus(balsa_app.main_window);
+    if (balsa_app.default_address_book == address_book)
+       balsa_app.default_address_book = NULL;
+
+    g_object_unref(address_book);
+
+    update_address_books();
+}
+
+static void
+pop3_add_cb(void)
+{
+    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_POP3);
+}
+
+static GtkWidget *
+server_add_menu_widget(void)
+{
+    GtkWidget *menu;
+    GtkWidget *menuitem;
+
+    menu = gtk_menu_new();
+    menuitem = gtk_menu_item_new_with_label(_("Remote POP3 mailbox…"));
+    g_signal_connect(G_OBJECT(menuitem), "activate",
+                     G_CALLBACK(pop3_add_cb), NULL);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    menuitem = gtk_menu_item_new_with_label(_("Remote IMAP mailbox…"));
+    g_signal_connect(G_OBJECT(menuitem), "activate",
+                    G_CALLBACK(mailbox_conf_add_imap_cb), NULL);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    menuitem = gtk_menu_item_new_with_label(_("Remote IMAP folder…"));
+    g_signal_connect(G_OBJECT(menuitem), "activate",
+                    G_CALLBACK(folder_conf_add_imap_cb), NULL);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+    return menu;
+}
+
+static void
+server_del_cb(GtkTreeView * tree_view)
+{
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    BalsaMailboxNode *mbnode;
+
+    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+       return;
+
+    gtk_tree_model_get(model, &iter, MS_DATA_COLUMN, &mbnode, -1);
+    g_return_if_fail(mbnode);
+
+    if (mbnode->mailbox)
+       mailbox_conf_delete(mbnode);
+    else
+       folder_conf_delete(mbnode);
+}
+
+static void
+timer_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate = 
+       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+                                     (pui->check_mail_auto));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->check_mail_minutes), newstate);
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+browse_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->browse_wrap));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->browse_wrap_length), newstate);
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+mark_quoted_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->mark_quoted));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->quote_pattern), newstate);
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+wrap_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->wordwrap));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->wraplength), newstate);
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+pgdown_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->pgdownmod));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->pgdown_percent), newstate);
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+option_menu_cb(GtkMenuItem * widget, gpointer data)
+{
+    /* update the index number */
+    gint *index = (gint *) data;
+    *index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
+}
+
+static void
+mailbox_close_timer_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+                                     (pui->close_mailbox_auto));
+
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->close_mailbox_minutes),
+                            newstate);
+
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+filter_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->hide_deleted)))
+       pui->filter |= (1 << 0);
+    else
+       pui->filter &= ~(1 << 0);
+
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+expunge_on_close_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+                                     (pui->expunge_on_close));
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->expunge_auto), newstate);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->expunge_auto),
+                                 newstate);
+
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+expunge_auto_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean newstate =
+        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->expunge_auto));
+    gtk_widget_set_sensitive(GTK_WIDGET(pui->expunge_minutes), newstate);
+
+    properties_modified_cb(widget, pbox);
+}
+
+static void
+imap_toggled_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    properties_modified_cb(widget, pbox);
+
+    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->check_imap)))
+       gtk_widget_set_sensitive(GTK_WIDGET(pui->check_imap_inbox), TRUE);
+    else {
+       gtk_toggle_button_set_active(
+           GTK_TOGGLE_BUTTON(pui->check_imap_inbox), FALSE);
+       gtk_widget_set_sensitive(GTK_WIDGET(pui->check_imap_inbox), FALSE);
+    }
+}
+
+static void
+convert_8bit_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    properties_modified_cb(widget, pbox);
+
+    gtk_widget_set_sensitive
+        (pui->convert_unknown_8bit_codeset,
+         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+                                      (pui->convert_unknown_8bit[1])));
+}
+
+/*
+ * Callbacks for the font group
+ */
+
+static void
+use_system_fonts_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean use_custom_fonts =
+        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+
+    properties_modified_cb(widget, pbox);
+
+    gtk_widget_set_sensitive(pui->message_font_label, use_custom_fonts);
+    gtk_widget_set_sensitive(pui->message_font_button, use_custom_fonts);
+    gtk_widget_set_sensitive(pui->subject_font_label, use_custom_fonts);
+    gtk_widget_set_sensitive(pui->subject_font_button, use_custom_fonts);
+    gtk_widget_set_sensitive(pui->use_default_font_size, use_custom_fonts);
+}
+
+static void
+font_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    gboolean show_size =
+        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
+                                      (pui->use_default_font_size));
+
+    properties_modified_cb(widget, pbox);
+
+    gtk_font_button_set_show_size(GTK_FONT_BUTTON(widget), show_size);
+    g_object_set_data(G_OBJECT(widget), "font-modified",
+                      GINT_TO_POINTER(TRUE));
+}
+
+static void
+default_font_size_cb(GtkWidget * widget, GtkWidget * pbox)
+{
+    if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+        /* Changing from default font size to user-specified font size;
+         * we make sure the font size is not initially zero. */
+        font_button_check_font_size(pui->message_font_button, widget);
+        font_button_check_font_size(pui->subject_font_button, widget);
+    }
+
+    font_modified_cb(pui->message_font_button, pbox);
+    font_modified_cb(pui->subject_font_button, pbox);
+}
+
+/*
+ * End of callbacks for the font group
+ */
+
+
+static void
+response_cb(GtkDialog * dialog, gint response, gpointer data)
+{
+    switch (response) {
+    case GTK_RESPONSE_APPLY:
+        apply_prefs(dialog);
+        break;
+    case GTK_RESPONSE_HELP:
+        balsa_help_pbox_display();
+        break;
+    case GTK_RESPONSE_OK:
+        apply_prefs(dialog);
+        /* and fall through to... */
+    default:
+        destroy_pref_window_cb();
+        gtk_widget_destroy(GTK_WIDGET(dialog));
+    }
+}
+
+/*
+ * End of callbacks
+ */
+
+/**************************************************************
+ *
+ * Preference groups
  *
- * Mail options page
+ * Each group is given a GtkGrid, and appends a row containing
+ * the group title, followed by rows with the group's controls.
  *
- ******************/
+ *************************************************************/
 
 /*
- * Mail server subpage
+ * Remote mailbox servers group
  */
 
 static void
@@ -1776,6 +1999,10 @@ pm_grid_add_remote_mailbox_servers_group(GtkWidget * grid_widget)
     update_mail_servers();
 }
 
+/*
+ * Local mail directory group
+ */
+
 static void
 pm_grid_add_local_mail_group(GtkWidget * grid_widget)
 {
@@ -1792,6 +2019,10 @@ pm_grid_add_local_mail_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Outgoing mail servers group
+ */
+
 static void
 pm_grid_add_outgoing_mail_group(GtkWidget * grid_widget)
 {
@@ -1854,20 +2085,8 @@ pm_grid_add_outgoing_mail_group(GtkWidget * grid_widget)
     update_smtp_servers();
 }
 
-static GtkWidget *
-mailserver_subpage()
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_remote_mailbox_servers_group(grid);
-    pm_grid_add_local_mail_group(grid);
-    pm_grid_add_outgoing_mail_group(grid);
-
-    return grid;
-}
-
 /*
- * Incoming sub-page
+ * Checking group
  */
 
 static void
@@ -1944,6 +2163,10 @@ pm_grid_add_checking_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * MDN request group
+ */
+
 static void
 pm_grid_add_mdn_group(GtkWidget * grid_widget)
 {
@@ -1993,19 +2216,8 @@ pm_grid_add_mdn_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-incoming_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_checking_group(grid);
-    pm_grid_add_mdn_group(grid);
-
-    return grid;
-}
-
 /*
- * Outgoing subpage
+ * Word wrap group
  */
 
 static void
@@ -2035,6 +2247,10 @@ pm_grid_add_word_wrap_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Other options group
+ */
+
 static void
 pm_grid_add_other_options_group(GtkWidget * grid_widget)
 {
@@ -2065,50 +2281,8 @@ pm_grid_add_other_options_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-outgoing_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_word_wrap_group(grid);
-    pm_grid_add_other_options_group(grid);
-
-    return grid;
-}
-
 /*
- * The page
- */
-
-static GtkWidget *
-create_mail_options_page(GtkTreeStore * store)
-{
-    GtkWidget *notebook;
-    GtkTreeIter iter;
-
-    notebook = gtk_notebook_new();
-    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
-    gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
-
-    gtk_tree_store_append(store, &iter, NULL);
-    pm_append_page(notebook, mailserver_subpage(), _("Mail servers"),
-                   store, &iter);
-    pm_append_page(notebook, incoming_subpage(), _("Incoming"),
-                   store, &iter);
-    pm_append_page(notebook, outgoing_subpage(), _("Outgoing"),
-                   store, &iter);
-
-    return notebook;
-}
-
-/**********************
- *
- * Display options page
- *
- *********************/
-
-/*
- * Display subpage
+ * Main window group
  */
 
 static void
@@ -2125,7 +2299,8 @@ pm_grid_add_main_window_group(GtkWidget * grid_widget)
         pm_grid_attach_check(grid, 1, ++row, 3, 1, _("Use preview pane"));
 
     pui->mblist_show_mb_content_info =
-        pm_grid_attach_check(grid, 1, ++row, 3, 1, _("Show mailbox statistics in left pane"));
+        pm_grid_attach_check(grid, 1, ++row, 3, 1,
+                             _("Show message counts in mailbox list"));
 
     pui->layout_type = create_layout_types_menu();
     pm_grid_attach(grid, pui->layout_type, 1, ++row, 2, 1);
@@ -2148,11 +2323,15 @@ pm_grid_add_main_window_group(GtkWidget * grid_widget)
 
     label = gtk_label_new(_("percent"));
     gtk_widget_set_halign(label, GTK_ALIGN_START);
-    pm_grid_attach(grid, label, 2, row, 1, 1);
+    pm_grid_attach(grid, label, 3, row, 1, 1);
 
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Message window group
+ */
+
 static void
 pm_grid_add_message_window_group(GtkWidget * grid_widget)
 {
@@ -2171,19 +2350,8 @@ pm_grid_add_message_window_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-display_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_main_window_group(grid);
-    pm_grid_add_message_window_group(grid);
-
-    return grid;
-}
-
 /*
- * Threading subpage
+ * Sorting and threading group
  */
 
 static void
@@ -2191,16 +2359,19 @@ pm_grid_add_threading_group(GtkWidget * grid_widget)
 {
     GtkGrid *grid = (GtkGrid *) grid_widget;
     gint row = pm_grid_get_next_row(grid);
+    GtkWidget *label;
 
     pm_grid_attach(grid, pm_group_label(_("Sorting and threading")), 0, row, 3, 1);
 
-    pm_grid_attach_label(grid, 1, ++row, 1, 1, _("Default sort column:"));
+    label = pm_grid_attach_label(grid, 1, ++row, 1, 1, _("Default sort column:"));
+    gtk_widget_set_hexpand(label, FALSE);
     pui->default_sort_field =
         pm_grid_attach_pref_menu(grid, 2, row, 1, 1,
                                  sort_field_label, G_N_ELEMENTS(sort_field_label),
                                  &pui->sort_field_index);
 
-    pm_grid_attach_label(grid, 1, ++row, 1, 1, _("Default threading style:"));
+    label = pm_grid_attach_label(grid, 1, ++row, 1, 1, _("Default threading style:"));
+    gtk_widget_set_hexpand(label, FALSE);
     pui->default_threading_type =
         pm_grid_attach_pref_menu(grid, 2, row, 1, 1,
                                  threading_type_label, NUM_THREADING_STYLES,
@@ -2212,22 +2383,8 @@ pm_grid_add_threading_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-threading_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_threading_group(grid);
-
-    return grid;
-}
-
-/*
- * Message subpage
- */
-
 /*
- * Font group
+ * Fonts group
  */
 
 /*
@@ -2297,7 +2454,7 @@ pm_grid_add_preview_font_group(GtkWidget * grid_widget)
 }
 
 /*
- * End of font group
+ * Quoted and flowed text group
  */
 
 static void
@@ -2330,6 +2487,10 @@ pm_grid_add_quoted_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Multipart group
+ */
+
 static void
 pm_grid_add_alternative_group(GtkWidget * grid_widget)
 {
@@ -2347,20 +2508,8 @@ pm_grid_add_alternative_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-message_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_preview_font_group(grid);
-    pm_grid_add_quoted_group(grid);
-    pm_grid_add_alternative_group(grid);
-
-    return grid;
-}
-
 /*
- * Colors subpage
+ * Message colors group
  */
 
 static void
@@ -2383,6 +2532,10 @@ pm_grid_add_message_colors_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Link color group
+ */
+
 static void
 pm_grid_add_link_color_group(GtkWidget * grid_widget)
 {
@@ -2396,19 +2549,8 @@ pm_grid_add_link_color_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-colors_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_message_colors_group(grid);
-    pm_grid_add_link_color_group(grid);
-
-    return grid;
-}
-
 /*
- * Format subpage
+ * Format group
  */
 
 static void
@@ -2427,6 +2569,10 @@ pm_grid_add_display_formats_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Broken 8-bit group
+ */
+
 static void
 pm_grid_add_broken_8bit_codeset_group(GtkWidget * grid_widget)
 {
@@ -2464,19 +2610,8 @@ pm_grid_add_broken_8bit_codeset_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-format_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_display_formats_group(grid);
-    pm_grid_add_broken_8bit_codeset_group(grid);
-
-    return grid;
-}
-
 /*
- * Status messages subpage
+ * Information messages group
  */
 
 static void
@@ -2511,6 +2646,10 @@ pm_grid_add_information_messages_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Progress dialog group
+ */
+
 static void
 pm_grid_add_progress_group(GtkWidget * grid_widget)
 {
@@ -2533,57 +2672,10 @@ pm_grid_add_progress_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-status_messages_subpage(void)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_information_messages_group(grid);
-    pm_grid_add_progress_group(grid);
-
-    return grid;
-}
-
 /*
- * The page
+ * Address books group
  */
 
-static GtkWidget *
-create_display_page(GtkTreeStore * store)
-{
-    GtkWidget *notebook;
-    GtkTreeIter iter;
-
-    notebook = gtk_notebook_new();
-    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
-    gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
-
-    gtk_tree_store_append(store, &iter, NULL);
-    pm_append_page(notebook, display_subpage(), _("Layout"),
-                   store, &iter);
-    pm_append_page(notebook, threading_subpage(), _("Sort and thread"),
-                   store, &iter);
-    pm_append_page(notebook, message_subpage(), _("Message"),
-                   store, &iter);
-    pm_append_page(notebook, colors_subpage(), _("Colors"),
-                   store, &iter);
-    pm_append_page(notebook, format_subpage(), _("Format"),
-                   store, &iter);
-    pm_append_page(notebook, status_messages_subpage(), _("Status messages"),
-                   store, &iter);
-
-    return notebook;
-}
-
-/********************
- *
- * Address books page
- *
- *******************/
-
-static void address_book_change(LibBalsaAddressBook * address_book,
-                                gboolean append);
-
 static void
 pm_grid_add_address_books_group(GtkWidget * grid_widget)
 {
@@ -2676,24 +2768,7 @@ pm_grid_add_address_books_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-create_address_book_page(GtkTreeStore * store)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_address_books_group(grid);
-
-    return grid;
-}
-
-#if !HAVE_GTKSPELL
-
-/***************
- *
- * Spelling page
- *
- **************/
-
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
 static void
 pm_grid_add_misc_spelling_group(GtkWidget * grid_widget)
 {
@@ -2710,23 +2785,11 @@ pm_grid_add_misc_spelling_group(GtkWidget * grid_widget)
 
     pm_grid_set_next_row(grid, ++row);
 }
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
-static GtkWidget *
-create_spelling_page(GtkTreeStore * store)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_misc_spelling_group(grid);
-
-    return grid;
-}
-#endif                          /* HAVE_GTKSPELL */
-
-/***************
- *
- * Start-up page
- *
- **************/
+/*
+ * Startup options group
+ */
 
 static void
 pm_grid_add_startup_options_group(GtkWidget * grid_widget)
@@ -2747,6 +2810,10 @@ pm_grid_add_startup_options_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Folder scanning group
+ */
+
 static void
 pm_grid_add_folder_scanning_group(GtkWidget * grid_widget)
 {
@@ -2785,22 +2852,9 @@ pm_grid_add_folder_scanning_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
-static GtkWidget *
-create_startup_page(GtkTreeStore * store)
-{
-    GtkWidget *grid = pm_grid_new();
-
-    pm_grid_add_startup_options_group(grid);
-    pm_grid_add_folder_scanning_group(grid);
-
-    return grid;
-}
-
-/********************
- *
- * Miscellaneous page
- *
- *******************/
+/*
+ * Miscellaneous group
+ */
 
 static void
 pm_grid_add_misc_group(GtkWidget * grid_widget)
@@ -2834,6 +2888,10 @@ pm_grid_add_misc_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/*
+ * Message deleting group
+ */
+
 static void
 pm_grid_add_deleting_messages_group(GtkWidget * grid_widget)
 {
@@ -2879,603 +2937,577 @@ pm_grid_add_deleting_messages_group(GtkWidget * grid_widget)
     pm_grid_set_next_row(grid, ++row);
 }
 
+/***************************
+ *
+ * End of preferences groups
+ *
+ **************************/
+
+/*
+ * pm_append_page
+ *
+ * Put the child on the stack, and populate the tree store data
+ */
+
+static void
+pm_append_page(GtkWidget    * stack,
+               GtkWidget    * child,
+               const gchar  * text,
+               GtkTreeStore * store,
+               GtkTreeIter  * iter)
+{
+    gtk_stack_add_named((GtkStack *) stack, child, text);
+
+    gtk_tree_store_set(store, iter,
+                       PM_TEXT_COL, gettext(text),
+                       PM_HELP_COL, text,
+                       PM_CHILD_COL, child,
+                       -1);
+}
+
+/********************************************************
+ *
+ * The pages
+ *
+ * Each page consists of its own GtkGrid, which it passes
+ * to the various groups that belong on that page.
+ *
+ *******************************************************/
+
 static GtkWidget *
-create_misc_page(GtkTreeStore * store)
+pm_mailserver_page(void)
 {
     GtkWidget *grid = pm_grid_new();
 
-    pm_grid_add_misc_group(grid);
-    pm_grid_add_deleting_messages_group(grid);
+    pm_grid_add_remote_mailbox_servers_group(grid);
+    pm_grid_add_local_mail_group(grid);
+    pm_grid_add_outgoing_mail_group(grid);
 
     return grid;
 }
 
-
-/*
- * callbacks
- */
-static void
-properties_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+static GtkWidget *
+pm_incoming_page(void)
 {
-    gtk_dialog_set_response_sensitive(GTK_DIALOG(pbox), GTK_RESPONSE_OK,
-                                      TRUE);
-    gtk_dialog_set_response_sensitive(GTK_DIALOG(pbox), GTK_RESPONSE_APPLY,
-                                      TRUE);
+    GtkWidget *grid = pm_grid_new();
+
+    pm_grid_add_checking_group(grid);
+    pm_grid_add_mdn_group(grid);
+
+    return grid;
 }
 
-static void
-server_edit_cb(GtkTreeView * tree_view)
+static GtkWidget *
+pm_outgoing_page(void)
 {
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    BalsaMailboxNode *mbnode;
+    GtkWidget *grid = pm_grid_new();
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-       return;
+    pm_grid_add_word_wrap_group(grid);
+    pm_grid_add_other_options_group(grid);
 
-    gtk_tree_model_get(model, &iter, MS_DATA_COLUMN, &mbnode, -1);
-    g_return_if_fail(mbnode);
-    balsa_mailbox_node_show_prop_dialog(mbnode);
+    return grid;
 }
 
-/* Clear and populate the list. */
-static void
-update_smtp_servers(void)
+static GtkWidget *
+pm_display_page(void)
 {
-    GtkTreeView *tree_view;
-    GtkTreeSelection *selection;
-    GtkTreeIter iter;
-    GtkTreePath *path = NULL;
-    GtkTreeModel *model;
-    GSList *list;
+    GtkWidget *grid = pm_grid_new();
 
-    if (pui == NULL)
-        return;
+    pm_grid_add_main_window_group(grid);
+    pm_grid_add_message_window_group(grid);
 
-    tree_view = GTK_TREE_VIEW(pui->smtp_servers);
-    selection = gtk_tree_view_get_selection(tree_view);
-    if (gtk_tree_selection_get_selected(selection, &model, &iter))
-        path = gtk_tree_model_get_path(model, &iter);
+    return grid;
+}
 
-    gtk_list_store_clear(GTK_LIST_STORE(model));
+static GtkWidget *
+pm_threading_page(void)
+{
+    GtkWidget *grid = pm_grid_new();
 
-    for (list = balsa_app.smtp_servers; list; list = list->next) {
-        LibBalsaSmtpServer *smtp_server = LIBBALSA_SMTP_SERVER(list->data);
-        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                           0, libbalsa_smtp_server_get_name(smtp_server),
-                           1, smtp_server, -1);
-    }
+    pm_grid_add_threading_group(grid);
 
-    if (path) {
-        gtk_tree_selection_select_path(selection, path);
-        gtk_tree_path_free(path);
-    }
+    return grid;
 }
 
-#define SMTP_SERVER_SECTION_PREFIX "smtp-server-"
-
-/* Callback for the server-dialog's response handler. */
-static void
-smtp_server_update(LibBalsaSmtpServer * smtp_server,
-                   GtkResponseType response, const gchar * old_name)
+static GtkWidget *
+pm_message_page(void)
 {
-    gchar *group;
-    const gchar *new_name;
-
-    new_name = libbalsa_smtp_server_get_name(smtp_server);
-
-    if (old_name) {
-        /* We were editing an existing server. */
-        if (strcmp(old_name, new_name) == 0)
-           return;
-       else {
-            /* Name was changed. */
-            group =
-                g_strconcat(SMTP_SERVER_SECTION_PREFIX, old_name, NULL);
-            libbalsa_conf_remove_group(group);
-            g_free(group);
-        }
-    } else {
-        /* Populating a new server. */
-        if (response == GTK_RESPONSE_OK)
-            libbalsa_smtp_server_add_to_list(smtp_server,
-                                             &balsa_app.smtp_servers);
-        else {
-            /*  The user killed the dialog. */
-            g_object_unref(smtp_server);
-            return;
-        }
-    }
+    GtkWidget *grid = pm_grid_new();
 
-    update_smtp_servers();
+    pm_grid_add_preview_font_group(grid);
+    pm_grid_add_quoted_group(grid);
+    pm_grid_add_alternative_group(grid);
 
-    group = g_strconcat(SMTP_SERVER_SECTION_PREFIX, new_name, NULL);
-    libbalsa_conf_push_group(group);
-    g_free(group);
-    libbalsa_smtp_server_save_config(smtp_server);
-    libbalsa_conf_pop_group();
+    return grid;
 }
 
-static void
-smtp_server_add_cb(void)
+static GtkWidget *
+pm_colors_page(void)
 {
-    LibBalsaSmtpServer *smtp_server;
+    GtkWidget *grid = pm_grid_new();
 
-    smtp_server = libbalsa_smtp_server_new();
-    libbalsa_smtp_server_dialog(smtp_server,
-                                GTK_WINDOW(property_box),
-                                smtp_server_update);
+    pm_grid_add_message_colors_group(grid);
+    pm_grid_add_link_color_group(grid);
+
+    return grid;
 }
 
-static void
-smtp_server_edit_cb(GtkTreeView * tree_view)
+static GtkWidget *
+pm_format_page(void)
 {
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    LibBalsaSmtpServer *smtp_server;
+    GtkWidget *grid = pm_grid_new();
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-        return;
+    pm_grid_add_display_formats_group(grid);
+    pm_grid_add_broken_8bit_codeset_group(grid);
 
-    gtk_tree_model_get(model, &iter, 1, &smtp_server, -1);
-    g_return_if_fail(smtp_server);
-    libbalsa_smtp_server_dialog(smtp_server,
-                                GTK_WINDOW(property_box),
-                                smtp_server_update);
+    return grid;
 }
 
-static void
-smtp_server_del_cb(GtkTreeView * tree_view)
+static GtkWidget *
+pm_status_messages_page(void)
 {
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    LibBalsaSmtpServer *smtp_server;
-    gchar *group;
+    GtkWidget *grid = pm_grid_new();
 
-    /* Nothing to do if no server is selected, or if it is the last one. */
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter)
-        || gtk_tree_model_iter_n_children(model, NULL) <= 1)
-        return;
+    pm_grid_add_information_messages_group(grid);
+    pm_grid_add_progress_group(grid);
 
-    gtk_tree_model_get(model, &iter, 1, &smtp_server, -1);
-    g_return_if_fail(smtp_server);
+    return grid;
+}
 
-    group = g_strconcat(SMTP_SERVER_SECTION_PREFIX,
-                        libbalsa_smtp_server_get_name(smtp_server), NULL);
-    libbalsa_conf_remove_group(group);
-    g_free(group);
+static GtkWidget *
+create_address_book_page(void)
+{
+    GtkWidget *grid = pm_grid_new();
 
-    balsa_app.smtp_servers =
-        g_slist_remove(balsa_app.smtp_servers, smtp_server);
-    g_object_unref(smtp_server);
-    update_smtp_servers();
+    pm_grid_add_address_books_group(grid);
+
+    return grid;
 }
 
-/* Set sensitivity of the Modify and Delete buttons; we can edit a server
- * only if one is selected, and we can delete one only if it is selected
- * and it is not the last server. */
-static void
-smtp_server_changed(GtkTreeSelection * selection, gpointer user_data)
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
+static GtkWidget *
+pm_spelling_page(void)
 {
-    gboolean selected;
-    GtkTreeModel *model;
+    GtkWidget *grid = pm_grid_new();
 
-    selected = gtk_tree_selection_get_selected(selection, &model, NULL);
-    gtk_widget_set_sensitive(pui->smtp_server_edit_button, selected);
-    gtk_widget_set_sensitive(pui->smtp_server_del_button,
-                             selected
-                             && gtk_tree_model_iter_n_children(model,
-                                                               NULL) > 1);
-}
+    pm_grid_add_misc_spelling_group(grid);
 
-/* Address book callbacks */
+    return grid;
+}
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
-static void
-address_book_change(LibBalsaAddressBook * address_book, gboolean append)
+static GtkWidget *
+pm_startup_page(void)
 {
-    if (append) {
-        balsa_app.address_book_list =
-            g_list_append(balsa_app.address_book_list, address_book);
-       balsa_window_update_book_menus(balsa_app.main_window);
-    }
-    config_address_book_save(address_book);
-    update_address_books();
+    GtkWidget *grid = pm_grid_new();
+
+    pm_grid_add_startup_options_group(grid);
+    pm_grid_add_folder_scanning_group(grid);
+
+    return grid;
 }
 
-static void
-address_book_edit_cb(GtkTreeView * tree_view)
+static GtkWidget *
+pm_misc_page(void)
 {
-    LibBalsaAddressBook *address_book;
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
+    GtkWidget *grid = pm_grid_new();
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-       return;
+    pm_grid_add_misc_group(grid);
+    pm_grid_add_deleting_messages_group(grid);
 
-    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+    return grid;
+}
 
-    g_assert(address_book != NULL);
+/*
+ * End of pages
+ */
 
-    balsa_address_book_config_new(address_book, address_book_change,
-                                  GTK_WINDOW(property_box));
-}
+/*********************************************************************
+ *
+ * Sections
+ *
+ * A section consists of several pages (that is, more than one)
+ * covering a given part of the UI. It is given an iter for the parent
+ * node in the GtkTreeView, and creates child iters for the children.
+ *
+ ********************************************************************/
 
 static void
-address_book_set_default_cb(GtkTreeView * tree_view)
+create_mail_options_section(GtkTreeStore * store,
+                            GtkTreeIter  * parent,
+                            GtkWidget    * stack)
 {
-    LibBalsaAddressBook *address_book;
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
     GtkTreeIter iter;
-    GtkTreePath *path;
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-       return;
-
-    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+    pm_append_page(stack, pm_mailserver_page(), N_("Mail options"),
+                   store, parent);
 
-    g_assert(address_book != NULL);
-    balsa_app.default_address_book = address_book;
-
-    path = gtk_tree_model_get_path(model, &iter);
-    update_address_books();
-    gtk_tree_selection_select_path(selection, path);
-    gtk_tree_path_free(path);
-}
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_incoming_page(), N_("Incoming"),
+                   store, &iter);
 
-static void
-add_menu_cb(GtkWidget * menu, GtkWidget * widget)
-{
-    gtk_widget_show_all(menu);
-#if GTK_CHECK_VERSION(3, 22, 0)
-    gtk_menu_popup_at_widget(GTK_MENU(menu), GTK_WIDGET(widget),
-                             GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST,
-                             NULL);
-#else                           /*GTK_CHECK_VERSION(3, 22, 0) */
-    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0,
-                   gtk_get_current_event_time());
-#endif                          /*GTK_CHECK_VERSION(3, 22, 0) */
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_outgoing_page(), N_("Outgoing"),
+                   store, &iter);
 }
 
 static void
-address_book_delete_cb(GtkTreeView * tree_view)
+create_display_section(GtkTreeStore * store,
+                       GtkTreeIter  * parent,
+                       GtkWidget    * stack)
 {
-    LibBalsaAddressBook *address_book;
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
     GtkTreeIter iter;
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-       return;
+    pm_append_page(stack, pm_display_page(), N_("Display options"),
+                   store, parent);
 
-    gtk_tree_model_get(model, &iter, AB_DATA_COLUMN, &address_book, -1);
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_threading_page(), N_("Sort and thread"),
+                   store, &iter);
 
-    g_assert(address_book != NULL);
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_message_page(), N_("Message"),
+                   store, &iter);
 
-    config_address_book_delete(address_book);
-    balsa_app.address_book_list =
-       g_list_remove(balsa_app.address_book_list, address_book);
-    balsa_window_update_book_menus(balsa_app.main_window);
-    if (balsa_app.default_address_book == address_book)
-       balsa_app.default_address_book = NULL;
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_colors_page(), N_("Colors"),
+                   store, &iter);
 
-    g_object_unref(address_book);
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_format_page(), N_("Format"),
+                   store, &iter);
 
-    update_address_books();
+    gtk_tree_store_append(store, &iter, parent);
+    pm_append_page(stack, pm_status_messages_page(), N_("Status messages"),
+                   store, &iter);
 }
 
-static void
-pop3_add_cb(void)
-{
-    mailbox_conf_new(LIBBALSA_TYPE_MAILBOX_POP3);
-}
+/*
+ * End of sections
+ */
 
-static GtkWidget *
-server_add_menu_widget(void)
+/*
+ * Idle handler for open_preferences_manager
+ */
+
+static gboolean
+open_preferences_manager_idle(void)
 {
-    GtkWidget *menu;
-    GtkWidget *menuitem;
+    gchar *name;
 
-    menu = gtk_menu_new();
-    menuitem = gtk_menu_item_new_with_label(_("Remote POP3 mailbox…"));
-    g_signal_connect(G_OBJECT(menuitem), "activate",
-                     G_CALLBACK(pop3_add_cb), NULL);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-    menuitem = gtk_menu_item_new_with_label(_("Remote IMAP mailbox…"));
-    g_signal_connect(G_OBJECT(menuitem), "activate",
-                    G_CALLBACK(mailbox_conf_add_imap_cb), NULL);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-    menuitem = gtk_menu_item_new_with_label(_("Remote IMAP folder…"));
-    g_signal_connect(G_OBJECT(menuitem), "activate",
-                    G_CALLBACK(folder_conf_add_imap_cb), NULL);
-    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+    gdk_threads_enter();
 
-    return menu;
-}
+    if (pui == NULL) {
+        gdk_threads_leave();
+        return FALSE;
+    }
 
-static void
-server_del_cb(GtkTreeView * tree_view)
-{
-    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
-    GtkTreeModel *model;
-    GtkTreeIter iter;
-    BalsaMailboxNode *mbnode;
+    name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER
+                                         (pui->mail_directory));
+    if (!name || strcmp(name, balsa_app.local_mail_directory) != 0) {
+        /* Chooser still hasn't been initialized. */
+        g_free(name);
+        gdk_threads_leave();
+        return TRUE;
+    }
+    g_free(name);
 
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-       return;
+    g_signal_connect(pui->mail_directory, "selection-changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    gtk_tree_model_get(model, &iter, MS_DATA_COLUMN, &mbnode, -1);
-    g_return_if_fail(mbnode);
+    gdk_threads_leave();
+    return FALSE;
+}                               /* open_preferences_manager_idle */
 
-    if (mbnode->mailbox)
-       mailbox_conf_delete(mbnode);
-    else
-       folder_conf_delete(mbnode);
-}
+/****************
+ *
+ * Public methods
+ *
+ ***************/
 
 void
-timer_modified_cb(GtkWidget * widget, GtkWidget * pbox)
+open_preferences_manager(GtkWidget * widget, gpointer data)
 {
-    gboolean newstate = 
-       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
-                                     (pui->check_mail_auto));
+    GtkWidget *hbox;
+    GtkTreeStore *store;
+    GtkWidget *view;
+    GtkTreeSelection * selection;
+    GtkWidget *stack;
+    GtkWidget *active_win = data;
+    gint i;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+    GtkTreeIter iter;
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->check_mail_minutes), newstate);
-    properties_modified_cb(widget, pbox);
-}
+    /* only one preferences manager window */
+    if (already_open) {
+        gtk_window_present(GTK_WINDOW(property_box));
+        return;
+    }
 
-static void
-browse_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->browse_wrap));
+    pui = g_malloc(sizeof(PropertyUI));
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->browse_wrap_length), newstate);
-    properties_modified_cb(widget, pbox);
-}
+    property_box =              /* must NOT be modal */
+        gtk_dialog_new_with_buttons(_("Balsa Preferences"),
+                                    GTK_WINDOW(active_win),
+                                    GTK_DIALOG_DESTROY_WITH_PARENT |
+                                    libbalsa_dialog_flags(),
+                                    _("_OK"), GTK_RESPONSE_OK,
+                                    _("_Apply"), GTK_RESPONSE_APPLY,
+                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                    _("_Help"), GTK_RESPONSE_HELP,
+                                    NULL);
+#if HAVE_MACOSX_DESKTOP
+    libbalsa_macosx_menu_for_parent(property_box, GTK_WINDOW(active_win));
+#endif
 
-static void
-mark_quoted_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->mark_quoted));
+    hbox = gtk_dialog_get_content_area(GTK_DIALOG(property_box));
+    gtk_orientable_set_orientation(GTK_ORIENTABLE(hbox),
+                                   GTK_ORIENTATION_HORIZONTAL);
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->quote_pattern), newstate);
-    properties_modified_cb(widget, pbox);
-}
+    store = gtk_tree_store_new(PM_NUM_COLS,
+                               G_TYPE_STRING,   /* PM_TEXT_COL     */
+                               G_TYPE_STRING,   /* PM_HELP_COL     */
+                               GTK_TYPE_WIDGET  /* PM_CHILD_COL    */
+            );
+    pui->view = view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    g_object_set(view, "margin", BORDER_WIDTH, NULL);
+    gtk_container_add(GTK_CONTAINER(hbox), view);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
 
-static void
-wrap_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->wordwrap));
+    renderer = gtk_cell_renderer_text_new();
+    column =
+        gtk_tree_view_column_new_with_attributes(NULL, renderer,
+                                                 "text", PM_TEXT_COL,
+                                                 NULL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->wraplength), newstate);
-    properties_modified_cb(widget, pbox);
-}
+    stack = gtk_stack_new();
+    gtk_stack_set_transition_type((GtkStack *) stack,
+                                  GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
+    gtk_stack_set_transition_duration((GtkStack *) stack, 400);
+    gtk_container_add(GTK_CONTAINER(hbox), stack);
 
-static void
-pgdown_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->pgdownmod));
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+    g_signal_connect(selection, "changed",
+                     G_CALLBACK(pm_selection_changed), stack);
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->pgdown_percent), newstate);
-    properties_modified_cb(widget, pbox);
-}
+    already_open = TRUE;
 
-static void
-option_menu_cb(GtkMenuItem * widget, gpointer data)
-{
-    /* update the index number */
-    gint *index = (gint *) data;
-    *index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
-}
+    gtk_window_set_resizable(GTK_WINDOW(property_box), FALSE);
+    g_object_set_data(G_OBJECT(property_box), "balsawindow", active_win);
 
-static GtkWidget *
-create_pref_option_menu(const gchar * names[], gint size, gint * index)
-{
-    GtkWidget *combo_box;
-    gint i;
+    /* Create the pages */
+    gtk_tree_store_append(store, &iter, NULL);
+    create_mail_options_section(store, &iter, stack);
 
-    combo_box = pm_combo_box_new();
-    g_signal_connect(G_OBJECT(combo_box), "changed",
-                     G_CALLBACK(option_menu_cb), index);
+    gtk_tree_store_append(store, &iter, NULL);
+    create_display_section(store, &iter, stack);
 
-    for (i = 0; i < size; i++)
-       add_show_menu(_(names[i]), i, combo_box);
+    gtk_tree_store_append(store, &iter, NULL);
+    pm_append_page(stack, create_address_book_page(),
+                   N_("Address books"), store, &iter);
 
-    return combo_box;
-}
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
+    gtk_tree_store_append(store, &iter, NULL);
+    pm_append_page(stack, pm_spelling_page(),
+                   N_("Spelling"), store, &iter);
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
+    gtk_tree_store_append(store, &iter, NULL);
+    pm_append_page(stack, pm_startup_page(),
+                   N_("Start-up"), store, &iter);
 
-static void
-add_show_menu(const char* label, gint level, GtkWidget* menu)
-{
-    struct pm_combo_box_info *info =
-        g_object_get_data(G_OBJECT(menu), PM_COMBO_BOX_INFO);
+    gtk_tree_store_append(store, &iter, NULL);
+    pm_append_page(stack, pm_misc_page(),
+                   N_("Miscellaneous"), store, &iter);
 
-    gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(menu), label);
-    info->levels = g_slist_append(info->levels, GINT_TO_POINTER(level));
-}
+    gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
 
-static GtkWidget *
-create_information_message_menu(void)
-{
-    GtkWidget *combo_box = pm_combo_box_new();
+    set_prefs();
+    /* Now that all the prefs have been set, we must desensitize the
+     * buttons. */
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(property_box),
+                                      GTK_RESPONSE_OK, FALSE);
+    gtk_dialog_set_response_sensitive(GTK_DIALOG(property_box),
+                                      GTK_RESPONSE_APPLY, FALSE);
 
-    add_show_menu(_("Show nothing"),       BALSA_INFORMATION_SHOW_NONE,
-                  combo_box);
-    add_show_menu(_("Show dialog"),        BALSA_INFORMATION_SHOW_DIALOG,
-                  combo_box);
-    add_show_menu(_("Show in list"),       BALSA_INFORMATION_SHOW_LIST,
-                  combo_box);
-    add_show_menu(_("Show in status bar"), BALSA_INFORMATION_SHOW_BAR,
-                  combo_box);
-    add_show_menu(_("Print to console"),   BALSA_INFORMATION_SHOW_STDERR,
-                  combo_box);
+    for (i = 0; i < NUM_PWINDOW_MODES; i++) {
+        g_signal_connect(G_OBJECT(pui->pwindow_type[i]), "clicked",
+                         G_CALLBACK(properties_modified_cb), property_box);
+    }
 
-    return combo_box;
-}
+    g_signal_connect(G_OBJECT(pui->previewpane), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->layout_type), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->view_message_on_open), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->ask_before_select), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->pgdownmod), "toggled",
+                     G_CALLBACK(pgdown_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->pgdown_percent), "changed",
+                     G_CALLBACK(pgdown_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->debug), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static GtkWidget *
-create_mdn_reply_menu(void)
-{
-    GtkWidget *combo_box = pm_combo_box_new();
+    g_signal_connect(G_OBJECT(pui->mblist_show_mb_content_info), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+#if !(HAVE_GSPELL || HAVE_GTKSPELL)
+    g_signal_connect(G_OBJECT(pui->spell_check_sig), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->spell_check_quoted), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+#endif                          /* !(HAVE_GSPELL || HAVE_GTKSPELL) */
 
-    add_show_menu(_("Never"),  BALSA_MDN_REPLY_NEVER,  combo_box);
-    add_show_menu(_("Ask me"), BALSA_MDN_REPLY_ASKME,  combo_box);
-    add_show_menu(_("Always"), BALSA_MDN_REPLY_ALWAYS, combo_box);
+    /* Connect signal in an idle handler, after the file chooser has
+     * been initialized. */
+    g_idle_add_full(G_PRIORITY_LOW,
+                    (GSourceFunc) open_preferences_manager_idle,
+                    NULL, NULL);
+    g_signal_connect(G_OBJECT(pui->check_mail_auto), "toggled",
+                     G_CALLBACK(timer_modified_cb), property_box);
 
-    return combo_box;
-}
+    g_signal_connect(G_OBJECT(pui->check_mail_minutes), "changed",
+                     G_CALLBACK(timer_modified_cb), property_box);
 
-void
-mailbox_close_timer_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
-                                     (pui->close_mailbox_auto));
+    g_signal_connect(G_OBJECT(pui->quiet_background_check), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->msg_size_limit), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->close_mailbox_minutes),
-                            newstate);
+    g_signal_connect(G_OBJECT(pui->check_imap), "toggled",
+                     G_CALLBACK(imap_toggled_cb), property_box);
 
-    properties_modified_cb(widget, pbox);
-}
+    g_signal_connect(G_OBJECT(pui->check_imap_inbox), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static void
-filter_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->hide_deleted)))
-       pui->filter |= (1 << 0);
-    else
-       pui->filter &= ~(1 << 0);
+    g_signal_connect(G_OBJECT(pui->notify_new_mail_dialog), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    properties_modified_cb(widget, pbox);
-}
+    g_signal_connect(G_OBJECT(pui->notify_new_mail_sound), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static void
-expunge_on_close_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
-                                     (pui->expunge_on_close));
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->expunge_auto), newstate);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->expunge_auto),
-                                 newstate);
+    g_signal_connect(G_OBJECT(pui->notify_new_mail_icon), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    properties_modified_cb(widget, pbox);
-}
+    g_signal_connect(G_OBJECT(pui->close_mailbox_auto), "toggled",
+                     G_CALLBACK(mailbox_close_timer_modified_cb),
+                     property_box);
+    g_signal_connect(G_OBJECT(pui->close_mailbox_minutes), "changed",
+                     G_CALLBACK(mailbox_close_timer_modified_cb),
+                     property_box);
 
-static void
-expunge_auto_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean newstate =
-        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->expunge_auto));
-    gtk_widget_set_sensitive(GTK_WIDGET(pui->expunge_minutes), newstate);
+    g_signal_connect(G_OBJECT(pui->hide_deleted), "toggled",
+                     G_CALLBACK(filter_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->expunge_on_close), "toggled",
+                     G_CALLBACK(expunge_on_close_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->expunge_auto), "toggled",
+                     G_CALLBACK(expunge_auto_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->expunge_minutes), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    properties_modified_cb(widget, pbox);
-}
+    g_signal_connect(G_OBJECT(pui->browse_wrap), "toggled",
+                     G_CALLBACK(browse_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->browse_wrap_length), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->wordwrap), "toggled",
+                     G_CALLBACK(wrap_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->wraplength), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->always_queue_sent_mail), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->copy_to_sentbox), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->autoquote), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->reply_include_html_parts), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->forward_attached), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static void imap_toggled_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    properties_modified_cb(widget, pbox);
+    /* external editor */
+    g_signal_connect(G_OBJECT(pui->edit_headers), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->check_imap)))
-       gtk_widget_set_sensitive(GTK_WIDGET(pui->check_imap_inbox), TRUE);
-    else {
-       gtk_toggle_button_set_active(
-           GTK_TOGGLE_BUTTON(pui->check_imap_inbox), FALSE);
-       gtk_widget_set_sensitive(GTK_WIDGET(pui->check_imap_inbox), FALSE);
-    }
-}
+    /* arp */
+    g_signal_connect(G_OBJECT(pui->quote_str), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->mark_quoted), "toggled",
+                     G_CALLBACK(mark_quoted_modified_cb),
+                     property_box);
+    g_signal_connect(G_OBJECT(pui->quote_pattern), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static void 
-convert_8bit_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    properties_modified_cb(widget, pbox);
+    /* multipart/alternative */
+    g_signal_connect(G_OBJECT(pui->display_alt_plain), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    gtk_widget_set_sensitive
-        (pui->convert_unknown_8bit_codeset,
-         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
-                                      (pui->convert_unknown_8bit[1])));
-}
+    /* convert 8-bit text with no charset header */
+    g_signal_connect(G_OBJECT(pui->convert_unknown_8bit_codeset),
+                     "changed", G_CALLBACK(properties_modified_cb),
+                     property_box);
 
-/*
- * Callbacks for the font group
- */
+    /* message font */
+    g_signal_connect(G_OBJECT(pui->use_system_fonts), "toggled",
+                     G_CALLBACK(use_system_fonts_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->message_font_button), "font-set",
+                     G_CALLBACK(font_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->subject_font_button), "font-set",
+                     G_CALLBACK(font_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->use_default_font_size), "toggled",
+                     G_CALLBACK(default_font_size_cb), property_box);
 
-static void
-use_system_fonts_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean use_custom_fonts =
-        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
 
-    properties_modified_cb(widget, pbox);
+    g_signal_connect(G_OBJECT(pui->open_inbox_upon_startup), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->check_mail_upon_startup), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->remember_open_mboxes), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    gtk_widget_set_sensitive(pui->message_font_label, use_custom_fonts);
-    gtk_widget_set_sensitive(pui->message_font_button, use_custom_fonts);
-    gtk_widget_set_sensitive(pui->subject_font_label, use_custom_fonts);
-    gtk_widget_set_sensitive(pui->subject_font_button, use_custom_fonts);
-    gtk_widget_set_sensitive(pui->use_default_font_size, use_custom_fonts);
-}
+    g_signal_connect(G_OBJECT(pui->local_scan_depth), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
+    g_signal_connect(G_OBJECT(pui->imap_scan_depth), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static void
-font_modified_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    gboolean show_size =
-        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
-                                      (pui->use_default_font_size));
+    g_signal_connect(G_OBJECT(pui->empty_trash), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    properties_modified_cb(widget, pbox);
+    /* threading */
+    g_signal_connect(G_OBJECT(pui->tree_expand_check), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    gtk_font_button_set_show_size(GTK_FONT_BUTTON(widget), show_size);
-    g_object_set_data(G_OBJECT(widget), "font-modified",
-                      GINT_TO_POINTER(TRUE));
-}
 
-static void
-default_font_size_cb(GtkWidget * widget, GtkWidget * pbox)
-{
-    if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
-        /* Changing from default font size to user-specified font size;
-         * we make sure the font size is not initially zero. */
-        font_button_check_font_size(pui->message_font_button, widget);
-        font_button_check_font_size(pui->subject_font_button, widget);
-    }
+    /* Date format */
+    g_signal_connect(G_OBJECT(pui->date_format), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-    font_modified_cb(pui->message_font_button, pbox);
-    font_modified_cb(pui->subject_font_button, pbox);
-}
+    /* Selected headers */
+    g_signal_connect(G_OBJECT(pui->selected_headers), "changed",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-/*
- * End of callbacks for the font group
- */
+    /* Colour */
+    for (i = 0; i < MAX_QUOTED_COLOR; i++)
+        g_signal_connect(G_OBJECT(pui->quoted_color[i]), "released",
+                         G_CALLBACK(properties_modified_cb), property_box);
 
-static GtkWidget *
-create_layout_types_menu(void)
-{
-    GtkWidget *combo_box = pm_combo_box_new();
-    add_show_menu(_("Default layout"), LAYOUT_DEFAULT, combo_box);
-    add_show_menu(_("Wide message layout"), LAYOUT_WIDE_MSG, combo_box);
-    add_show_menu(_("Wide screen layout"), LAYOUT_WIDE_SCREEN, combo_box);
-    return combo_box;
-}
+    g_signal_connect(G_OBJECT(pui->url_color), "released",
+                     G_CALLBACK(properties_modified_cb), property_box);
 
-static GtkWidget *
-create_action_after_move_menu(void)
-{
-    GtkWidget *combo_box = pm_combo_box_new();
-    add_show_menu(_("Show next unread message"), NEXT_UNREAD, combo_box);
-    add_show_menu(_("Show next message"), NEXT, combo_box);
-    add_show_menu(_("Close message window"), CLOSE, combo_box);
-    return combo_box;
-}
+    /* handling of message parts with 8-bit chars without codeset headers */
+    for (i = 0; i < NUM_CONVERT_8BIT_MODES; i++)
+        g_signal_connect(G_OBJECT(pui->convert_unknown_8bit[i]), "toggled",
+                         G_CALLBACK(convert_8bit_cb), property_box);
+
+    /* Gnome Property Box Signals */
+    g_signal_connect(G_OBJECT(property_box), "response",
+                     G_CALLBACK(response_cb), NULL);
+
+    gtk_widget_show_all(GTK_WIDGET(property_box));
+
+}                               /* open_preferences_manager */
 
 /* refresh any data displayed in the preferences manager
  * window in case it has changed */
@@ -3488,149 +3520,61 @@ refresh_preferences_manager(void)
                                  balsa_app.browse_wrap);
 }
 
-static void
-balsa_help_pbox_display(void)
+/* update_mail_servers:
+   update mail server list in the preferences window.
+   NOTE: it can be called even when the preferences window is closed (via
+   mailbox context menu) - and it should check for it.
+ */
+void
+update_mail_servers(void)
 {
-    GtkTreeSelection *selection;
+    GtkTreeView *tree_view;
     GtkTreeModel *model;
     GtkTreeIter iter;
-    GtkTreeIter parent;
-    gchar *text, *p;
-    GError *err = NULL;
-    gchar *uri;
-#if GTK_CHECK_VERSION(3, 22, 0)
-    GtkWidget *toplevel;
-#else /* GTK_CHECK_VERSION(3, 22, 0) */
-    GdkScreen *screen;
-#endif /* GTK_CHECK_VERSION(3, 22, 0) */
-    GString *string;
+    GList *list;
+    gchar *protocol;
+    GtkTreeModel *app_model;
+    gboolean valid;
+    BalsaMailboxNode *mbnode;
 
-    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pui->view));
-    if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+    if (pui == NULL)
         return;
 
-    string = g_string_new("help:balsa/preferences-");
+    tree_view = GTK_TREE_VIEW(pui->mail_servers);
+    model = gtk_tree_view_get_model(tree_view);
 
-    if (gtk_tree_model_iter_parent(model, &parent, &iter)) {
-        gtk_tree_model_get(model, &parent, PM_HELP_COL, &text, -1);
-        for (p = text; *p; p++)
-            *p = (*p == ' ') ? '-' : g_ascii_tolower(*p);
-        g_string_append(string, text);
-        g_free(text);
-        g_string_append_c(string, '#');
-    }
-    gtk_tree_model_get(model, &iter, PM_HELP_COL, &text, -1);
-    for (p = text; *p; p++)
-        *p = (*p == ' ') ? '-' : g_ascii_tolower(*p);
-    g_string_append(string, text);
-    g_free(text);
+    gtk_list_store_clear(GTK_LIST_STORE(model));
+    for (list = balsa_app.inbox_input; list; list = list->next) {
+        if (!(mbnode = list->data))
+            continue;
+        if (LIBBALSA_IS_MAILBOX_POP3(mbnode->mailbox))
+            protocol = "POP3";
+        else if (LIBBALSA_IS_MAILBOX_IMAP(mbnode->mailbox))
+            protocol = "IMAP";
+        else
+            protocol = _("Unknown");
 
-    uri = g_string_free(string, FALSE);
-#if GTK_CHECK_VERSION(3, 22, 0)
-    toplevel = gtk_widget_get_toplevel(GTK_WIDGET(pui->view));
-    if (gtk_widget_is_toplevel(toplevel)) {
-        gtk_show_uri_on_window(GTK_WINDOW(toplevel), uri,
-                               gtk_get_current_event_time(), &err);
-    }
-#else  /* GTK_CHECK_VERSION(3, 22, 0) */
-    screen = gtk_widget_get_screen(pui->view);
-    gtk_show_uri(screen, uri, gtk_get_current_event_time(), &err);
-#endif /* GTK_CHECK_VERSION(3, 22, 0) */
-    if (err) {
-        balsa_information(LIBBALSA_INFORMATION_WARNING,
-               _("Error displaying %s: %s\n"),
-               uri, err->message);
-        g_error_free(err);
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                           MS_PROT_COLUMN, protocol,
+                           MS_NAME_COLUMN, mbnode->mailbox->name,
+                           MS_DATA_COLUMN, mbnode, -1);
     }
-
-    g_free(uri);
-}
-
-
-/* combo boxes */
-
-static void
-pm_combo_box_info_free(struct pm_combo_box_info * info)
-{
-    g_slist_free(info->levels);
-    g_free(info);
-}
-
-static GtkWidget *
-pm_combo_box_new(void)
-{
-    GtkWidget *combo_box = gtk_combo_box_text_new();
-    struct pm_combo_box_info *info = g_new0(struct pm_combo_box_info, 1);
-
-    gtk_widget_set_hexpand(combo_box, TRUE);
-
-    g_object_set_data_full(G_OBJECT(combo_box), PM_COMBO_BOX_INFO, info,
-                           (GDestroyNotify) pm_combo_box_info_free);
-    g_signal_connect(G_OBJECT(combo_box), "changed",
-                     G_CALLBACK(properties_modified_cb), property_box);
-
-    return combo_box;
-}
-
-static void
-pm_combo_box_set_level(GtkWidget * combo_box, gint level)
-{
-    struct pm_combo_box_info *info =
-        g_object_get_data(G_OBJECT(combo_box), PM_COMBO_BOX_INFO);
-    GSList *list;
-    guint i;
-
-    for (list = info->levels, i = 0; list; list = list->next, ++i)
-       if (GPOINTER_TO_INT(list->data) == level) {
-           gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), i);
-           break;
-       }
-}
-
-static gint
-pm_combo_box_get_level(GtkWidget * combo_box)
-{
-    struct pm_combo_box_info *info =
-        g_object_get_data(G_OBJECT(combo_box), PM_COMBO_BOX_INFO);
-    gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
-
-    return GPOINTER_TO_INT(g_slist_nth_data(info->levels, active));
-}
-
-static void
-pm_append_page(GtkWidget * notebook, GtkWidget * widget,
-               const gchar * text, GtkTreeStore * store,
-               GtkTreeIter * parent_iter)
-{
-    GtkTreeIter iter;
-    guint page = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
-
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-                             widget, gtk_label_new(text));
-
-    if (parent_iter && page == 0) {
-        /* We'll show the first child when the parent row is selected,
-         * so we don't create a row for it. */
-        gtk_tree_store_set(store, parent_iter,
-                           PM_CHILD_COL, notebook,
-                           -1);
-        return;
+    /*
+     * add other remote servers
+     *
+     * we'll check everything at the top level in the mailbox_nodes
+     * list:
+     */
+    app_model = GTK_TREE_MODEL(balsa_app.mblist_tree_store);
+    for (valid = gtk_tree_model_get_iter_first(app_model, &iter);
+         valid; valid = gtk_tree_model_iter_next(app_model, &iter)) {
+        gtk_tree_model_get(app_model, &iter, 0, &mbnode, -1);
+        add_other_server(mbnode, model);
+        g_object_unref(mbnode);
     }
 
-    if (GTK_IS_NOTEBOOK(widget)) {
-        /* The row for this widget was already created, to be the parent
-         * of the notebook's pages. */
-        GtkTreeModel *model = GTK_TREE_MODEL(store);
-        gint n_children =
-            gtk_tree_model_iter_n_children(model, parent_iter);
-        gtk_tree_model_iter_nth_child(model, &iter, parent_iter,
-                                      n_children - 1);
-    } else
-        gtk_tree_store_append(store, &iter, parent_iter);
-    gtk_tree_store_set(store, &iter,
-                       PM_TEXT_COL, _(text),
-                       PM_HELP_COL, text,
-                       PM_NOTEBOOK_COL, notebook,
-                       PM_PAGE_COL, page,
-                       -1);
+    if (gtk_tree_model_get_iter_first(model, &iter))
+        gtk_tree_selection_select_iter(gtk_tree_view_get_selection
+                                       (tree_view), &iter);
 }


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