mirror of https://github.com/djcb/mu.git
query: improve thread-date handling
And make it available in query_match, so we can expose it to elisp.
This commit is contained in:
parent
bed6058fdc
commit
8c9430a09a
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2021 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
** 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
|
** under the terms of the GNU General Public License as published by the
|
||||||
|
@ -94,8 +94,8 @@ struct QueryMatch {
|
||||||
std::string subject;
|
std::string subject;
|
||||||
std::string thread_subject; /**< the thread subject for this message */
|
std::string thread_subject; /**< the thread subject for this message */
|
||||||
size_t thread_level{}; /**< The thread level */
|
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_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_date{}; /**< date of newest message in thread */
|
||||||
|
|
||||||
bool operator<(const QueryMatch& rhs) const {
|
bool operator<(const QueryMatch& rhs) const {
|
||||||
return date_key < rhs.date_key;
|
return date_key < rhs.date_key;
|
||||||
|
|
|
@ -78,8 +78,11 @@ struct Container {
|
||||||
// of this container -- ie.. either the one from the first of its
|
// of this container -- ie.. either the one from the first of its
|
||||||
// children, or from its query-match, if it has no children.
|
// children, or from its query-match, if it has no children.
|
||||||
//
|
//
|
||||||
// That the sub-root-levels of thtreas are always sorted
|
// Note that the sub-root-levels of threads are always sorted by date,
|
||||||
// by date, in ascending order.
|
// in ascending order, regardless of whatever sorting was specified for
|
||||||
|
// the root-level.
|
||||||
|
|
||||||
|
|
||||||
std::string thread_date_key;
|
std::string thread_date_key;
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,7 +139,7 @@ handle_duplicates (IdTable& id_table, DupTable& dup_table)
|
||||||
|
|
||||||
// add duplicates as fake children
|
// add duplicates as fake children
|
||||||
char buf[32];
|
char buf[32];
|
||||||
::snprintf(buf, sizeof(buf), "bastard-%zu", ++n);
|
::snprintf(buf, sizeof(buf), "dup-%zu", ++n);
|
||||||
it->second.add_child(
|
it->second.add_child(
|
||||||
id_table.emplace(buf, std::move(dup.second)).first->second);
|
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
|
// both. Moreover, even when sorting the top-level in descending
|
||||||
// order, still sort the thread levels below that in ascending
|
// order, still sort the thread levels below that in ascending
|
||||||
// order.
|
// 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
|
// remember the subject, we use it to determine the (sub)thread subject
|
||||||
container.query_match->subject = mi.subject().value_or("");
|
container.query_match->subject = mi.subject().value_or("");
|
||||||
|
|
||||||
|
@ -233,7 +240,6 @@ determine_id_table (QueryResultsType& qres)
|
||||||
return id_table;
|
return id_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Recursively walk all containers under the root set.
|
/// Recursively walk all containers under the root set.
|
||||||
/// For each container:
|
/// For each container:
|
||||||
///
|
///
|
||||||
|
@ -451,15 +457,11 @@ static void
|
||||||
sort_container (Container& container)
|
sort_container (Container& container)
|
||||||
{
|
{
|
||||||
// 1. childless container.
|
// 1. childless container.
|
||||||
|
if (container.children.empty())
|
||||||
if (container.children.empty()) {
|
return; // no children; nothing to sort.
|
||||||
container.thread_date_key = container.query_match->date_key;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. container with children.
|
// 2. container with children.
|
||||||
// recurse, depth-first: sort the children
|
// recurse, depth-first: sort the children
|
||||||
|
|
||||||
for (auto& child: container.children)
|
for (auto& child: container.children)
|
||||||
sort_container(*child);
|
sort_container(*child);
|
||||||
|
|
||||||
|
@ -469,9 +471,11 @@ sort_container (Container& container)
|
||||||
return c1->thread_date_key < c2->thread_date_key;
|
return c1->thread_date_key < c2->thread_date_key;
|
||||||
});
|
});
|
||||||
|
|
||||||
// and 'bubble up' the date of the *newest* message*. We reasonably
|
// and 'bubble up' the date of the *newest* message with a date. We
|
||||||
// assume that it's later than its parent.
|
// reasonably assume that it's later than its parent.
|
||||||
container.thread_date_key = container.children.back()->thread_date_key;
|
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
|
// unsorted vec of root containers. We can
|
||||||
// only sort these _after_ sorting the children.
|
// only sort these _after_ sorting the children.
|
||||||
ContainerVec root_vec;
|
ContainerVec root_vec;
|
||||||
for (auto&& item: id_table)
|
for (auto&& item: id_table) {
|
||||||
if (!item.second.parent && !item.second.is_nuked)
|
if (!item.second.parent && !item.second.is_nuked)
|
||||||
root_vec.emplace_back(&item.second);
|
root_vec.emplace_back(&item.second);
|
||||||
|
}
|
||||||
|
|
||||||
// now sort all threads _under_ the root set (by date/ascending)
|
// now sort all threads _under_ the root set (by date/ascending)
|
||||||
for (auto&& c: root_vec) {
|
for (auto&& c: root_vec)
|
||||||
sort_container(*c);
|
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.
|
// and then sort the root set.
|
||||||
//
|
//
|
||||||
|
@ -553,7 +555,6 @@ calculate_threads_real (Results& qres, bool descending)
|
||||||
if (g_test_verbose())
|
if (g_test_verbose())
|
||||||
std::cout << "*** id-table(1):\n" << id_table << "\n";
|
std::cout << "*** id-table(1):\n" << id_table << "\n";
|
||||||
|
|
||||||
|
|
||||||
// // Step 2: get the root set
|
// // Step 2: get the root set
|
||||||
// // Step 3: discard id_table
|
// // Step 3: discard id_table
|
||||||
// Nope: id-table owns the containers.
|
// 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.)
|
// in the thread-path string (so we can lexically compare them.)
|
||||||
sort_siblings(id_table, descending);
|
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())
|
// if (g_test_verbose())
|
||||||
// std::cout << "*** id-table(2):\n" << id_table << "\n";
|
// std::cout << "*** id-table(2):\n" << id_table << "\n";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue