[balsa/threading: 7/16] Simplify threading



commit 3e207a09cbe77e4745e5ed9d73ee6598f04b948b
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sun Aug 19 13:14:02 2018 -0400

    Simplify threading
    
    Change THREADING_SIMPLE to mean JWZ without the 'subject gather'
    phase, and change the UI to enable or disable threading instead
    of offering the choice of threading algorithms.
    
    Still to do: add UI for choosing JWZ instead of SIMPLE.
    
    * libbalsa/mailbox.c (lbm_need_threading_idle_cb),
    (libbalsa_mailbox_set_view_filter), (lbm_set_threading_idle_cb),
    (lbm_set_threading), (libbalsa_mailbox_set_threading): do not
    pass threading type to _set_threading, just get it from the
    view.
    * libbalsa/mailbox.h: ditto.
    * libbalsa/mailbox_local.c (libbalsa_mailbox_local_close_mailbox),
    (lbml_set_threading), (lbml_set_threading_idle_cb),
    (libbalsa_mailbox_local_set_threading), (lbm_local_thread_idle),
    (lbml_thread_messages), (lbml_unthread_message),
    (lbml_threading_flat): change THREADING_SIMPLE to mean JWZ
    without the 'subject gather' phase, and simplify THREADING_FLAT.
    * src/balsa-index.c (balsa_index_set_threading_type): do nothing
    if the type has not changed.
    * src/balsa-index.h: the threading type is
    LibBalsaMailboxThreadingType.
    * src/main-window.c (threading_change_state),
    (bw_add_win_action_entries), (balsa_window_new),
    (bw_enable_expand_collapse), (bw_enable_mailbox_menus),
    (bw_set_thread_messages), (bw_real_open_mbnode_idle_cb): remove
    the threading type radio buttons, and replace them with a
    'Thread messages' check-box.
    * src/main.c (balsa_get_stats): new API for
    libbalsa_mailbox_set_threading.
    * src/pref-manager.c (update_view_defaults), (apply_prefs),
    (set_prefs), (pm_grid_add_threading_group),
    (open_preferences_manager): remove the threading type combo box,
    and replace it with a 'Thread messages by default' check-box.
    * ui/main-window.ui: remove the threading type radio buttons,
    and replace them with a 'Thread messages' check-box.

 ChangeLog                |  47 ++++++++++++----
 libbalsa/mailbox.c       |  23 ++++----
 libbalsa/mailbox.h       |   5 +-
 libbalsa/mailbox_local.c | 143 +++++++++++++----------------------------------
 src/balsa-index.c        |  12 ++--
 src/balsa-index.h        |   3 +-
 src/main-window.c        |  78 +++++++++-----------------
 src/main.c               |   5 +-
 src/pref-manager.c       |  50 ++++++++++-------
 ui/main-window.ui        |  15 +----
 10 files changed, 158 insertions(+), 223 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d0186c50e..95dddb459 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -37,21 +37,46 @@
          make BalsaWindow::progress_bar a weak pointer and test whether
          it is NULL before dereferencing.
 
-2018-08-27  Peter Bloomfield  <pbloomfield bellsouth net>
-
-       Check for valid msgno
+2018-08-19  Peter Bloomfield  <pbloomfield bellsouth net>
 
-       * libbalsa/mailbox.c (mbox_get_thread_date_traverse_func): check
-       that the msgno that we get from the GNode is in the valid range
-       1 <= msgno <= mindex->len.
+       Simplify threading
 
-2018-08-27  Peter Bloomfield  <pbloomfield bellsouth net>
+       Change THREADING_SIMPLE to mean JWZ without the 'subject gather'
+       phase, and change the UI to enable or disable threading instead
+       of offering the choice of threading algorithms.
 
-       Clear timeout source id in handler
+       Still to do: add UI for choosing JWZ instead of SIMPLE.
 
-       * libbalsa/mailbox_local.c (lbm_local_sync_real),
-       (lbm_local_sync_idle): clear LibBalsaMailboxLocal::sync_id in
-       the timeout handler, not in the thread that it creates.
+       * libbalsa/mailbox.c (lbm_need_threading_idle_cb),
+       (libbalsa_mailbox_set_view_filter), (lbm_set_threading_idle_cb),
+       (lbm_set_threading), (libbalsa_mailbox_set_threading): do not
+       pass threading type to _set_threading, just get it from the
+       view.
+       * libbalsa/mailbox.h: ditto.
+       * libbalsa/mailbox_local.c (libbalsa_mailbox_local_close_mailbox),
+       (lbml_set_threading), (lbml_set_threading_idle_cb),
+       (libbalsa_mailbox_local_set_threading), (lbm_local_thread_idle),
+       (lbml_thread_messages), (lbml_unthread_message),
+       (lbml_threading_flat): change THREADING_SIMPLE to mean JWZ
+       without the 'subject gather' phase, and simplify THREADING_FLAT.
+       * src/balsa-index.c (balsa_index_set_threading_type): do nothing
+       if the type has not changed.
+       * src/balsa-index.h: the threading type is
+       LibBalsaMailboxThreadingType.
+       * src/main-window.c (threading_change_state),
+       (bw_add_win_action_entries), (balsa_window_new),
+       (bw_enable_expand_collapse), (bw_enable_mailbox_menus),
+       (bw_set_thread_messages), (bw_real_open_mbnode_idle_cb): remove
+       the threading type radio buttons, and replace them with a
+       'Thread messages' check-box.
+       * src/main.c (balsa_get_stats): new API for
+       libbalsa_mailbox_set_threading.
+       * src/pref-manager.c (update_view_defaults), (apply_prefs),
+       (set_prefs), (pm_grid_add_threading_group),
+       (open_preferences_manager): remove the threading type combo box,
+       and replace it with a 'Thread messages by default' check-box.
+       * ui/main-window.ui: remove the threading type radio buttons,
+       and replace them with a 'Thread messages' check-box.
 
 2018-08-11  Albrecht Dreß  <albrecht dress arcor de>
 
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index bd2465328..aca4fffdb 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -570,9 +570,8 @@ libbalsa_mailbox_free_mindex(LibBalsaMailbox *mailbox)
     }
 }
 
-static gboolean lbm_set_threading(LibBalsaMailbox * mailbox,
-                                  LibBalsaMailboxThreadingType
-                                  thread_type);
+static gboolean lbm_set_threading(LibBalsaMailbox * mailbox);
+
 gboolean
 libbalsa_mailbox_open(LibBalsaMailbox * mailbox, GError **err)
 {
@@ -1345,8 +1344,7 @@ lbm_need_threading_idle_cb(LibBalsaMailbox *mailbox)
 {
     libbalsa_lock_mailbox(mailbox);
 
-    lbm_set_threading(mailbox, mailbox->view->threading_type);
-
+    lbm_set_threading(mailbox);
     mailbox->need_threading_idle_id = 0;
 
     libbalsa_unlock_mailbox(mailbox);
@@ -2198,7 +2196,7 @@ libbalsa_mailbox_set_view_filter(LibBalsaMailbox *mailbox,
     if (update_immediately && mailbox->view_filter_pending) {
         LIBBALSA_MAILBOX_GET_CLASS(mailbox)->update_view_filter(mailbox,
                                                                 cond);
-        retval = lbm_set_threading(mailbox, mailbox->view->threading_type);
+        retval = lbm_set_threading(mailbox);
         mailbox->view_filter_pending = FALSE;
     }
 
@@ -2264,18 +2262,18 @@ lbm_set_threading_idle_cb(LibBalsaMailbox * mailbox)
 {
     lbm_check_and_sort(mailbox);
     g_object_unref(mailbox);
-    return FALSE;
+
+    return G_SOURCE_REMOVE;
 }
 
 static gboolean
-lbm_set_threading(LibBalsaMailbox * mailbox,
-                  LibBalsaMailboxThreadingType thread_type)
+lbm_set_threading(LibBalsaMailbox * mailbox)
 {
     if (!MAILBOX_OPEN(mailbox))
         return FALSE;
 
     LIBBALSA_MAILBOX_GET_CLASS(mailbox)->set_threading(mailbox,
-                                                       thread_type);
+                                                       mailbox->view->threading_type);
     if (libbalsa_am_i_subthread()) {
         g_idle_add((GSourceFunc) lbm_set_threading_idle_cb, g_object_ref(mailbox));
     } else {
@@ -2286,14 +2284,13 @@ lbm_set_threading(LibBalsaMailbox * mailbox,
 }
 
 void
-libbalsa_mailbox_set_threading(LibBalsaMailbox *mailbox,
-                               LibBalsaMailboxThreadingType thread_type)
+libbalsa_mailbox_set_threading(LibBalsaMailbox *mailbox)
 {
     g_return_if_fail(mailbox != NULL);
     g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
 
     libbalsa_lock_mailbox(mailbox);
-    lbm_set_threading(mailbox, thread_type);
+    lbm_set_threading(mailbox);
     libbalsa_unlock_mailbox(mailbox);
 }
 
diff --git a/libbalsa/mailbox.h b/libbalsa/mailbox.h
index a966082b1..8d4f4f3cc 100644
--- a/libbalsa/mailbox.h
+++ b/libbalsa/mailbox.h
@@ -101,7 +101,7 @@ typedef enum {
  * update pref-manager.c so the preferences work correctly */
 typedef enum {
     LB_MAILBOX_THREADING_FLAT,
-    LB_MAILBOX_THREADING_SIMPLE,
+    LB_MAILBOX_THREADING_SIMPLE, /* JWZ without the subject-gather step */
     LB_MAILBOX_THREADING_JWZ
 } LibBalsaMailboxThreadingType;
 
@@ -518,8 +518,7 @@ gboolean libbalsa_mailbox_can_do(LibBalsaMailbox *mailbox,
     libbalsa_mailbox_set_msg_tree and libbalsa_mailbox_unlink_and_prepend
     are helpers for the subclass methods.
 */
-void libbalsa_mailbox_set_threading(LibBalsaMailbox *mailbox,
-                                   LibBalsaMailboxThreadingType thread_type);
+void libbalsa_mailbox_set_threading(LibBalsaMailbox *mailbox);
 void libbalsa_mailbox_set_msg_tree(LibBalsaMailbox * mailbox,
                                   GNode * msg_tree);
 void libbalsa_mailbox_unlink_and_prepend(LibBalsaMailbox * mailbox,
diff --git a/libbalsa/mailbox_local.c b/libbalsa/mailbox_local.c
index b2e944c6b..84cdc9e2c 100644
--- a/libbalsa/mailbox_local.c
+++ b/libbalsa/mailbox_local.c
@@ -756,12 +756,10 @@ libbalsa_mailbox_local_close_mailbox(LibBalsaMailbox * mailbox,
                                      mailbox->persistent_view_filter, TRUE);
 
     if (local->thread_id) {
-        /* Rethread immediately. */
-        LibBalsaMailboxThreadingType cur_type =
-            libbalsa_mailbox_get_threading_type(mailbox);
         g_source_remove(local->thread_id);
         local->thread_id = 0;
-        libbalsa_mailbox_set_threading(mailbox, cur_type);
+        /* Rethread immediately. */
+        libbalsa_mailbox_set_threading(mailbox);
     }
 
     if (local->save_tree_id) {
@@ -1102,9 +1100,8 @@ libbalsa_mailbox_local_load_messages(LibBalsaMailbox *mailbox,
  * Threading
  */
 
-static void lbml_threading_jwz(LibBalsaMailbox * mailbox);
-static void lbml_threading_simple(LibBalsaMailbox * mailbox,
-                                 LibBalsaMailboxThreadingType th_type);
+static void lbml_thread_messages(LibBalsaMailbox *mailbox, gboolean subject_gather);
+static void lbml_threading_flat(LibBalsaMailbox * mailbox);
 
 void 
 libbalsa_mailbox_local_set_threading_info(LibBalsaMailboxLocal * local)
@@ -1119,11 +1116,13 @@ lbml_set_threading(LibBalsaMailbox * mailbox,
 {
     switch (thread_type) {
     case LB_MAILBOX_THREADING_JWZ:
-        lbml_threading_jwz(mailbox);
+        lbml_thread_messages(mailbox, TRUE);
         break;
-    case LB_MAILBOX_THREADING_FLAT:
     case LB_MAILBOX_THREADING_SIMPLE:
-        lbml_threading_simple(mailbox, thread_type);
+        lbml_thread_messages(mailbox, FALSE);
+        break;
+    case LB_MAILBOX_THREADING_FLAT:
+        lbml_threading_flat(mailbox);
         break;
     }
 }
@@ -1138,8 +1137,9 @@ lbml_set_threading_idle_cb(LbmlSetThreadingInfo * info)
 {
     lbml_set_threading(info->mailbox, info->thread_type);
     g_object_unref(info->mailbox);
-    g_slice_free(LbmlSetThreadingInfo, info);
-    return FALSE;
+    g_free(info);
+
+    return G_SOURCE_REMOVE;
 }
 
 static void
@@ -1187,7 +1187,7 @@ libbalsa_mailbox_local_set_threading(LibBalsaMailbox * mailbox,
     if (libbalsa_am_i_subthread()) {
         LbmlSetThreadingInfo *info;
 
-        info = g_slice_new(LbmlSetThreadingInfo);
+        info = g_new(LbmlSetThreadingInfo, 1);
         info->mailbox = g_object_ref(mailbox);
         info->thread_type = thread_type;
         g_idle_add((GSourceFunc) lbml_set_threading_idle_cb, info);
@@ -1291,12 +1291,8 @@ lbm_local_thread_idle(LibBalsaMailboxLocal * local)
 
     libbalsa_lock_mailbox(mailbox);
 
-    if (MAILBOX_OPEN(mailbox)) {
-        LibBalsaMailboxThreadingType cur_type =
-            libbalsa_mailbox_get_threading_type(mailbox);
-
-        libbalsa_mailbox_set_threading(mailbox, cur_type);
-    }
+    if (MAILBOX_OPEN(mailbox))
+        libbalsa_mailbox_set_threading(mailbox);
     local->thread_id = 0;
 
     libbalsa_unlock_mailbox(mailbox);
@@ -1421,12 +1417,11 @@ libbalsa_mailbox_local_get_msg_part(LibBalsaMessage *msg,
 /*  Start of threading functions  */
 /*--------------------------------*/
 /*
- * This code includes two message threading functions.
- * The first is the implementation of jwz's algorithm describled at
- * http://www.jwz.org/doc/threading.html . The another is very simple and 
- * trivial one. If you confirm that your mailbox includes every threaded 
- * messages, the later will be enough. Those functions are selectable on
- * each mailbox by setting the 'type' member in BalsaIndex. If you don't need
+ * Threading is implementated using jwz's algorithm describled at
+ * http://www.jwz.org/doc/threading.html. It is implemented with an option
+ * to avoid the "subject gather" step, which is needed only if some
+ * messages do not have a valid and complete "References" header, and
+ * can otherwise be annoying. If you don't need
  * message threading functionality, just specify 'LB_MAILBOX_THREADING_FLAT'. 
  *
  * ymnk jcraft com
@@ -1475,7 +1470,7 @@ lbml_info_free(ThreadingInfo * ti)
 }
 
 static void
-lbml_threading_jwz(LibBalsaMailbox * mailbox)
+lbml_thread_messages(LibBalsaMailbox * mailbox, gboolean subject_gather)
 {
     /* This implementation of JWZ's algorithm uses a second tree, rooted
      * at ti.root, for the message IDs.  Each node in the second tree
@@ -1495,12 +1490,14 @@ lbml_threading_jwz(LibBalsaMailbox * mailbox)
     g_node_traverse(ti.root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
                    (GNodeTraverseFunc) lbml_prune, &ti);
 
-    /* Do the evil subject gather and merge on the second tree. */
-    ti.subject_table = g_hash_table_new(g_str_hash, g_str_equal);
-    g_node_children_foreach(ti.root, G_TRAVERSE_ALL,
-                           (GNodeForeachFunc) lbml_subject_gather, &ti);
-    g_node_children_foreach(ti.root, G_TRAVERSE_ALL,
-                           (GNodeForeachFunc) lbml_subject_merge, &ti);
+    if (subject_gather) {
+        /* Do the evil subject gather and merge on the second tree. */
+        ti.subject_table = g_hash_table_new(g_str_hash, g_str_equal);
+        g_node_children_foreach(ti.root, G_TRAVERSE_ALL,
+                                (GNodeForeachFunc) lbml_subject_gather, &ti);
+        g_node_children_foreach(ti.root, G_TRAVERSE_ALL,
+                                (GNodeForeachFunc) lbml_subject_merge, &ti);
+    }
 
     /* Traverse the second tree and reparent corresponding nodes in the
      * mailbox's msg_tree. */
@@ -1991,86 +1988,26 @@ lbml_clear_empty(GNode * msg_tree)
 }
 #endif                         /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
 
-/* yet another message threading function */
-
-static gboolean lbml_insert_message(GNode * node, ThreadingInfo * ti);
-static gboolean lbml_thread_message(GNode * node, ThreadingInfo * ti);
-
-static void
-lbml_threading_simple(LibBalsaMailbox * mailbox,
-                     LibBalsaMailboxThreadingType type)
-{
-    GNode *msg_tree = mailbox->msg_tree;
-    ThreadingInfo ti;
-
-    lbml_info_setup(mailbox, &ti);
-
-    if (type == LB_MAILBOX_THREADING_SIMPLE)
-       g_node_traverse(msg_tree, G_POST_ORDER, G_TRAVERSE_ALL,
-                       -1, (GNodeTraverseFunc) lbml_insert_message, &ti);
-
-    ti.type = type;
-    g_node_traverse(msg_tree, G_POST_ORDER, G_TRAVERSE_ALL, -1,
-                   (GNodeTraverseFunc) lbml_thread_message, &ti);
-
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
-    lbml_clear_empty(msg_tree);
-#endif                         /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
-
-    lbml_info_free(&ti);
-}
+/*------------------------------*/
+/*       Flat threading         */
+/*------------------------------*/
 
 static gboolean
-lbml_insert_message(GNode * node, ThreadingInfo * ti)
+lbml_unthread_message(GNode * node, LibBalsaMailbox * mailbox)
 {
-    LibBalsaMailboxLocalInfo *info;
-
-    if (!node->parent)
-       return FALSE;
-
-    info = lbml_get_info(node, ti);
-    if (!info)
-       return FALSE;
-
-    if (info->message_id)
-       g_hash_table_insert(ti->id_table, info->message_id, node);
+    if (node->parent != NULL && node->parent != mailbox->msg_tree)
+        libbalsa_mailbox_unlink_and_prepend(mailbox, node, mailbox->msg_tree);
 
     return FALSE;
 }
 
-static gboolean
-lbml_thread_message(GNode * node, ThreadingInfo * ti)
+static void
+lbml_threading_flat(LibBalsaMailbox * mailbox)
 {
-    if (!node->parent)
-        return FALSE;
-
-    if (ti->type == LB_MAILBOX_THREADING_FLAT) {
-        if (node->parent != ti->mailbox->msg_tree)
-            libbalsa_mailbox_unlink_and_prepend(ti->mailbox, node,
-                                                ti->mailbox->msg_tree);
-    } else {
-        LibBalsaMailboxLocalInfo *info;
-        GList *refs;
-        GNode *parent = NULL;
-
-        info = lbml_get_info(node, ti);
-        if (!info)
-            return FALSE;
-
-        refs = info->refs_for_threading;
-        if (refs)
-            parent = g_hash_table_lookup(ti->id_table,
-                                         g_list_last(refs)->data);
-
-        if (!parent)
-            parent = ti->mailbox->msg_tree;
-        if (parent != node->parent && parent != node
-            && !g_node_is_ancestor(node, parent))
-            libbalsa_mailbox_unlink_and_prepend(ti->mailbox, node, parent);
-    }
-
-    return FALSE;
+    g_node_traverse(mailbox->msg_tree, G_POST_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) lbml_unthread_message, mailbox);
 }
+
 /*------------------------------*/
 /*  End of threading functions  */
 /*------------------------------*/
diff --git a/src/balsa-index.c b/src/balsa-index.c
index ac551a007..d885520d7 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -2058,7 +2058,8 @@ balsa_index_update_tree(BalsaIndex * index, gboolean expand)
 
 /* balsa_index_set_threading_type: public method. */
 void
-balsa_index_set_threading_type(BalsaIndex * index, int thtype)
+balsa_index_set_threading_type(BalsaIndex * index,
+                               LibBalsaMailboxThreadingType threading_type)
 {
     LibBalsaMailbox *mailbox;
 
@@ -2067,12 +2068,15 @@ balsa_index_set_threading_type(BalsaIndex * index, int thtype)
     mailbox = index->mailbox_node->mailbox;
     g_return_if_fail(mailbox != NULL);
 
-    if (thtype != LB_MAILBOX_THREADING_FLAT
+    if (threading_type == libbalsa_mailbox_get_threading_type(mailbox))
+        return;
+
+    if (threading_type != LB_MAILBOX_THREADING_FLAT
         && !libbalsa_mailbox_prepare_threading(mailbox, 0))
         return;
-    libbalsa_mailbox_set_threading_type(mailbox, thtype);
 
-    libbalsa_mailbox_set_threading(mailbox, thtype);
+    libbalsa_mailbox_set_threading_type(mailbox, threading_type);
+    libbalsa_mailbox_set_threading(mailbox);
     balsa_index_update_tree(index, balsa_app.expand_tree);
 }
 
diff --git a/src/balsa-index.h b/src/balsa-index.h
index f5404f957..0f584f119 100644
--- a/src/balsa-index.h
+++ b/src/balsa-index.h
@@ -107,7 +107,8 @@ G_BEGIN_DECLS
                                           BalsaIndexWidthPreference pref);
     void balsa_index_scroll_on_open(BalsaIndex *index);
     void balsa_index_update_tree(BalsaIndex *bindex, gboolean expand);
-    void balsa_index_set_threading_type(BalsaIndex * bindex, int thtype);
+    void balsa_index_set_threading_type(BalsaIndex * bindex,
+                                        LibBalsaMailboxThreadingType threading_type);
     void balsa_index_set_view_filter(BalsaIndex *bindex,
                                      int filter_no,
                                      const gchar *filter_string,
diff --git a/src/main-window.c b/src/main-window.c
index 121b13a8c..6e77fcac3 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -142,7 +142,7 @@ static gboolean bw_is_open_mailbox(LibBalsaMailbox *m);
 
 static void bw_mailbox_tab_close_cb(GtkWidget * widget, gpointer data);
 
-static void bw_set_threading_menu(BalsaWindow * window, int option);
+static void bw_set_thread_messages(BalsaWindow * window, gboolean thread_messages);
 static void bw_show_mbtree(BalsaWindow * window);
 static void bw_set_filter_menu(BalsaWindow * window, int gui_filter);
 static LibBalsaCondition *bw_get_view_filter(BalsaWindow * window);
@@ -748,23 +748,6 @@ bw_action_get_boolean(BalsaWindow * window,
     return retval;
 }
 
-/*
- * Set the state of a radio action
- */
-
-static void
-bw_action_set_string(BalsaWindow * window,
-                     const gchar * action_name,
-                     const gchar * state)
-{
-    GAction *action;
-
-    action = bw_get_action(window, action_name);
-    if (action)
-        g_simple_action_set_state(G_SIMPLE_ACTION(action),
-                                  g_variant_new_string(state));
-}
-
 /*
  * Enable or disable an action
  */
@@ -1879,26 +1862,17 @@ threading_change_state(GSimpleAction * action,
 {
     BalsaWindow *window = BALSA_WINDOW(user_data);
     GtkWidget *index;
-    const gchar *value;
-    LibBalsaMailboxThreadingType type;
+    gboolean thread_messages;
+    LibBalsaMailboxThreadingType threading_type;
     BalsaMailboxNode *mbnode;
     LibBalsaMailbox *mailbox;
 
-    value = g_variant_get_string(state, NULL);
-
-    if (strcmp(value, "flat") == 0)
-        type = LB_MAILBOX_THREADING_FLAT;
-    else if (strcmp(value, "simple") == 0)
-        type = LB_MAILBOX_THREADING_SIMPLE;
-    else if (strcmp(value, "jwz") == 0)
-        type = LB_MAILBOX_THREADING_JWZ;
-    else {
-        g_print("%s unknown value “%s”\n", __func__, value);
-        return;
-    }
+    thread_messages = g_variant_get_boolean(state);
+    threading_type =
+        thread_messages ? LB_MAILBOX_THREADING_SIMPLE : LB_MAILBOX_THREADING_FLAT;
 
     index = balsa_window_find_current_index(window);
-    balsa_index_set_threading_type(BALSA_INDEX(index), type);
+    balsa_index_set_threading_type(BALSA_INDEX(index), threading_type);
 
     /* bw->current_index may have been destroyed and cleared during
      * set-threading: */
@@ -1972,7 +1946,7 @@ bw_add_win_action_entries(GActionMap * action_map)
                                   wrap_change_state},
         {"headers",               libbalsa_radio_activated, "s", "'none'",
                                   header_change_state},
-        {"threading",             libbalsa_radio_activated, "s", "'flat'",
+        {"threading",             libbalsa_toggle_activated, NULL, "false",
                                   threading_change_state},
         {"expand-all",            expand_all_activated},
         {"collapse-all",          collapse_all_activated},
@@ -2329,7 +2303,7 @@ balsa_window_new(GtkApplication *application)
 
     action = bw_get_action(window, "threading");
     g_simple_action_set_state(G_SIMPLE_ACTION(action),
-                              g_variant_new_string("flat"));
+                              g_variant_new_boolean(FALSE));
 
     bw_action_set_boolean(window, "show-mailbox-tabs",
                           balsa_app.show_notebook_tabs);
@@ -2401,7 +2375,10 @@ bw_enable_expand_collapse(BalsaWindow * window, LibBalsaMailbox * mailbox)
 {
     gboolean enable;
 
-    enable = mailbox &&
+    enable = mailbox != NULL;
+    bw_action_set_enabled(window, "threading", enable);
+
+    enable = mailbox != NULL &&
         libbalsa_mailbox_get_threading_type(mailbox) !=
         LB_MAILBOX_THREADING_FLAT;
     bw_action_set_enabled(window, "expand-all", enable);
@@ -2460,12 +2437,11 @@ bw_enable_mailbox_menus(BalsaWindow * window, BalsaIndex * index)
     bw_action_set_enabled(window, "remove-duplicates", mailbox &&
                           libbalsa_mailbox_can_move_duplicates(mailbox));
 
-    if (mailbox) {
-       bw_set_threading_menu(window,
-                                       libbalsa_mailbox_get_threading_type
-                                       (mailbox));
-       bw_set_filter_menu(window,
-                                    libbalsa_mailbox_get_filter(mailbox));
+    if (mailbox != NULL) {
+        bw_set_thread_messages(window,
+                               libbalsa_mailbox_get_threading_type(mailbox)
+                               != LB_MAILBOX_THREADING_FLAT);
+       bw_set_filter_menu(window, libbalsa_mailbox_get_filter(mailbox));
     }
 
     bw_enable_next_unread(window, libbalsa_mailbox_get_unread(mailbox) > 0
@@ -2650,19 +2626,18 @@ bw_enable_part_menu_items(BalsaWindow * window)
 }
 
 static void
-bw_set_threading_menu(BalsaWindow * window, int option)
+bw_set_thread_messages(BalsaWindow * window, gboolean thread_messages)
 {
     GtkWidget *index;
     BalsaMailboxNode *mbnode;
     LibBalsaMailbox *mailbox;
-    const gchar *const threading_types[] = { "flat", "simple", "jwz" };
 
-    bw_action_set_string(window, "threading", threading_types[option]);
+    bw_action_set_boolean(window, "threading", thread_messages);
 
-    if ((index = balsa_window_find_current_index(window))
-       && (mbnode = BALSA_INDEX(index)->mailbox_node)
-       && (mailbox = mbnode->mailbox))
-       bw_enable_expand_collapse(window, mailbox);
+    if ((index = balsa_window_find_current_index(window)) != NULL
+        && (mbnode = BALSA_INDEX(index)->mailbox_node) != NULL
+        && (mailbox = mbnode->mailbox) != NULL)
+        bw_enable_expand_collapse(window, mailbox);
 }
 
 static void
@@ -2896,9 +2871,8 @@ bw_real_open_mbnode_idle_cb(BalsaWindowRealOpenMbnodeInfo * info)
                                       page_num);
 
     bw_register_open_mailbox(mailbox);
-    libbalsa_mailbox_set_threading(mailbox,
-                                   libbalsa_mailbox_get_threading_type
-                                   (mailbox));
+
+    libbalsa_mailbox_set_threading(mailbox);
 
     filter =
         bw_get_condition_from_int(libbalsa_mailbox_get_filter(mailbox));
diff --git a/src/main.c b/src/main.c
index e8b61a1c6..24243f731 100644
--- a/src/main.c
+++ b/src/main.c
@@ -194,10 +194,9 @@ static void
 balsa_get_stats(long *unread, long *unsent)
 {
 
-    if(balsa_app.inbox && libbalsa_mailbox_open(balsa_app.inbox, NULL) ) {
+    if (balsa_app.inbox && libbalsa_mailbox_open(balsa_app.inbox, NULL)) {
         /* set threading type to load messages */
-        libbalsa_mailbox_set_threading(balsa_app.inbox,
-                                       balsa_app.inbox->view->threading_type);
+        libbalsa_mailbox_set_threading(balsa_app.inbox);
         *unread = balsa_app.inbox->unread_messages;
         libbalsa_mailbox_close(balsa_app.inbox, FALSE);
     } else *unread = -1;
diff --git a/src/pref-manager.c b/src/pref-manager.c
index 61c4035be..fcdca06b8 100644
--- a/src/pref-manager.c
+++ b/src/pref-manager.c
@@ -153,11 +153,10 @@ typedef struct _PropertyUI {
     GtkWidget *url_color;
 
     /* sorting and threading prefs */
-    GtkWidget *tree_expand_check;
     GtkWidget *default_sort_field;
     gint sort_field_index;
-    GtkWidget *default_threading_type;
-    gint threading_type_index;
+    GtkWidget *thread_messages_check;
+    GtkWidget *tree_expand_check;
 
     /* quote regex */
     GtkWidget *mark_quoted;
@@ -341,8 +340,14 @@ update_view_defaults(const gchar * group, const gchar * url,
         view->filter = pui->filter;
     if (view->sort_field == libbalsa_mailbox_get_sort_field(NULL))
         view->sort_field = pui->sort_field_index;
-    if (view->threading_type == libbalsa_mailbox_get_threading_type(NULL))
-        view->threading_type = pui->threading_type_index;
+    if (view->threading_type == libbalsa_mailbox_get_threading_type(NULL)) {
+        if (gtk_toggle_button_get_active
+            (GTK_TOGGLE_BUTTON(pui->thread_messages_check))) {
+            view->threading_type = LB_MAILBOX_THREADING_SIMPLE;
+        } else {
+            view->threading_type = LB_MAILBOX_THREADING_FLAT;
+        }
+    }
 
     if (!mailbox) {
         config_save_mailbox_view(url, view);
@@ -612,7 +617,15 @@ apply_prefs(GtkDialog * pbox)
 
     /* sorting and threading */
     libbalsa_mailbox_set_sort_field(NULL, pui->sort_field_index);
-    libbalsa_mailbox_set_threading_type(NULL, pui->threading_type_index);
+
+    { /* Scope */
+        gboolean thread_messages =
+            gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pui->thread_messages_check));
+        libbalsa_mailbox_set_threading_type(NULL, thread_messages ?
+                                            LB_MAILBOX_THREADING_SIMPLE :
+                                            LB_MAILBOX_THREADING_FLAT);
+    }
+
     balsa_app.expand_tree =
         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
                                      (pui->tree_expand_check));
@@ -814,14 +827,16 @@ set_prefs(void)
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->empty_trash),
                                  balsa_app.empty_trash_on_exit);
 
-    /* threading */
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->tree_expand_check),
-                                 balsa_app.expand_tree);
+    /* sorting and threading */
     pui->sort_field_index = libbalsa_mailbox_get_sort_field(NULL);
     pm_combo_box_set_level(pui->default_sort_field, pui->sort_field_index);
-    pui->threading_type_index = libbalsa_mailbox_get_threading_type(NULL);
-    pm_combo_box_set_level(pui->default_threading_type,
-                           pui->threading_type_index);
+
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->thread_messages_check),
+                                 libbalsa_mailbox_get_threading_type(NULL)
+                                 != LB_MAILBOX_THREADING_FLAT);
+
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->tree_expand_check),
+                                 balsa_app.expand_tree);
 
 #if !(HAVE_GSPELL || HAVE_GTKSPELL)
     /* spelling */
@@ -2406,13 +2421,8 @@ pm_grid_add_threading_group(GtkWidget * grid_widget)
                                  sort_field_label, G_N_ELEMENTS(sort_field_label),
                                  &pui->sort_field_index);
 
-    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,
-                                 &pui->threading_type_index);
-
+    pui->thread_messages_check =
+        pm_grid_attach_check(grid, 1, ++row, 2, 1, _("Thread messages by default"));
     pui->tree_expand_check =
         pm_grid_attach_check(grid, 1, ++row, 2, 1, _("Expand threads on open"));
 
@@ -3502,6 +3512,8 @@ open_preferences_manager(GtkWidget * widget, gpointer data)
                      G_CALLBACK(properties_modified_cb), property_box);
 
     /* threading */
+    g_signal_connect(G_OBJECT(pui->thread_messages_check), "toggled",
+                     G_CALLBACK(properties_modified_cb), property_box);
     g_signal_connect(G_OBJECT(pui->tree_expand_check), "toggled",
                      G_CALLBACK(properties_modified_cb), property_box);
 
diff --git a/ui/main-window.ui b/ui/main-window.ui
index 13f73a8f4..548da3366 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -262,21 +262,8 @@
       <section>
         <item>
           <attribute name='label'
-            translatable='yes'>_Flat index</attribute>
+            translatable='yes'>Th_read messages</attribute>
           <attribute name='action'>win.threading</attribute>
-          <attribute name='target'>flat</attribute>
-        </item>
-        <item>
-          <attribute name='label'
-            translatable='yes'>Si_mple threading</attribute>
-          <attribute name='action'>win.threading</attribute>
-          <attribute name='target'>simple</attribute>
-        </item>
-        <item>
-          <attribute name='label'
-            translatable='yes'>_JWZ threading</attribute>
-          <attribute name='action'>win.threading</attribute>
-          <attribute name='target'>jwz</attribute>
         </item>
       </section>
       <section>


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