From 8c9430a09a05492a7513292ed40f5822ce0d4987 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sun, 2 May 2021 23:18:16 +0300 Subject: [PATCH] query: improve thread-date handling And make it available in query_match, so we can expose it to elisp. --- lib/mu-query-results.hh | 6 +++--- lib/mu-query-threads.cc | 47 +++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/mu-query-results.hh b/lib/mu-query-results.hh index a74622b5..9376938b 100644 --- a/lib/mu-query-results.hh +++ b/lib/mu-query-results.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2020 Dirk-Jan C. Binnema +** Copyright (C) 2021 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -94,8 +94,8 @@ struct QueryMatch { std::string subject; std::string thread_subject; /**< the thread subject for this message */ size_t thread_level{}; /**< The thread level */ - std::string thread_path; /**< The hex-numerial path in the thread, ie. '00:01:0a' */ - std::string thread_date{}; /**< date of newest message in thread */ + std::string thread_path; /**< The hex-numerial path in the thread, ie. '00:01:0a' */ + std::string thread_date{}; /**< date of newest message in thread */ bool operator<(const QueryMatch& rhs) const { return date_key < rhs.date_key; diff --git a/lib/mu-query-threads.cc b/lib/mu-query-threads.cc index fefa57fb..947a7e8a 100644 --- a/lib/mu-query-threads.cc +++ b/lib/mu-query-threads.cc @@ -78,8 +78,11 @@ struct Container { // of this container -- ie.. either the one from the first of its // children, or from its query-match, if it has no children. // - // That the sub-root-levels of thtreas are always sorted - // by date, in ascending order. + // Note that the sub-root-levels of threads are always sorted by date, + // in ascending order, regardless of whatever sorting was specified for + // the root-level. + + std::string thread_date_key; @@ -136,7 +139,7 @@ handle_duplicates (IdTable& id_table, DupTable& dup_table) // add duplicates as fake children char buf[32]; - ::snprintf(buf, sizeof(buf), "bastard-%zu", ++n); + ::snprintf(buf, sizeof(buf), "dup-%zu", ++n); it->second.add_child( id_table.emplace(buf, std::move(dup.second)).first->second); } @@ -180,7 +183,11 @@ determine_id_table (QueryResultsType& qres) // both. Moreover, even when sorting the top-level in descending // order, still sort the thread levels below that in ascending // order. - container.query_match->date_key = mi.date().value_or(""); + container.thread_date_key = container.query_match->date_key = + mi.date().value_or(""); + // initial guess for the thread-date; might be updated + // later. + // remember the subject, we use it to determine the (sub)thread subject container.query_match->subject = mi.subject().value_or(""); @@ -233,7 +240,6 @@ determine_id_table (QueryResultsType& qres) return id_table; } - /// Recursively walk all containers under the root set. /// For each container: /// @@ -451,15 +457,11 @@ static void sort_container (Container& container) { // 1. childless container. - - if (container.children.empty()) { - container.thread_date_key = container.query_match->date_key; - return; - } + if (container.children.empty()) + return; // no children; nothing to sort. // 2. container with children. // recurse, depth-first: sort the children - for (auto& child: container.children) sort_container(*child); @@ -469,9 +471,11 @@ sort_container (Container& container) return c1->thread_date_key < c2->thread_date_key; }); - // and 'bubble up' the date of the *newest* message*. We reasonably - // assume that it's later than its parent. - container.thread_date_key = container.children.back()->thread_date_key; + // and 'bubble up' the date of the *newest* message with a date. We + // reasonably assume that it's later than its parent. + const auto& newest_date = container.children.back()->thread_date_key; + if (!newest_date.empty()) + container.thread_date_key = newest_date; } @@ -484,16 +488,14 @@ sort_siblings (IdTable& id_table, bool descending) // unsorted vec of root containers. We can // only sort these _after_ sorting the children. ContainerVec root_vec; - for (auto&& item: id_table) + for (auto&& item: id_table) { if (!item.second.parent && !item.second.is_nuked) root_vec.emplace_back(&item.second); + } // now sort all threads _under_ the root set (by date/ascending) - for (auto&& c: root_vec) { + for (auto&& c: root_vec) sort_container(*c); - if (c->query_match) // for debugging, remember - c->query_match->thread_date = c->thread_date_key; - } // and then sort the root set. // @@ -553,7 +555,6 @@ calculate_threads_real (Results& qres, bool descending) if (g_test_verbose()) std::cout << "*** id-table(1):\n" << id_table << "\n"; - // // Step 2: get the root set // // Step 3: discard id_table // Nope: id-table owns the containers. @@ -569,6 +570,12 @@ calculate_threads_real (Results& qres, bool descending) // in the thread-path string (so we can lexically compare them.) sort_siblings(id_table, descending); + // Step 7a:. update querymatches + for (auto&& item: id_table) { + Container& c{item.second}; + if (c.query_match) + c.query_match->thread_date = c.thread_date_key; + } // if (g_test_verbose()) // std::cout << "*** id-table(2):\n" << id_table << "\n"; }