Skip to content
Snippets Groups Projects
Commit 5e99bace authored by nenomius's avatar nenomius
Browse files

Do less work when building completion trie

Convert to lower case only once per string.
parent 6f05cebf
No related branches found
No related tags found
No related merge requests found
Pipeline #3439 failed
......@@ -22,54 +22,53 @@ CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
{
setSourceModel(model);
// insert all the full texts
auto insertParts = [this](const QString &str, int id) {
QTextBoundaryFinder finder(QTextBoundaryFinder::BoundaryType::Word, str);
finder.toStart();
do {
auto start = finder.position();
finder.toNextBoundary();
auto end = finder.position();
auto ref = str.midRef(start, end - start).trimmed();
if (!ref.isEmpty())
trie_.insert<ElementRank::second>(ref.toUcs4(), id);
} while (finder.position() < str.size());
};
const auto start_at = std::chrono::steady_clock::now();
// insert full texts and partial matches
for (int i = 0; i < sourceModel()->rowCount(); i++) {
if (static_cast<size_t>(i) < max_completions_)
mapping.push_back(i);
// full texts are ranked first and partial matches second
// that way when searching full texts will be first in result list
auto string1 = sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
.toString()
.toLower();
if (!string1.isEmpty())
trie_.insert(string1.toUcs4(), i);
if (!string1.isEmpty()) {
trie_.insert<ElementRank::first>(string1.toUcs4(), i);
insertParts(string1, i);
}
auto string2 = sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
.toString()
.toLower();
if (!string2.isEmpty())
trie_.insert(string2.toUcs4(), i);
if (!string2.isEmpty()) {
trie_.insert<ElementRank::first>(string2.toUcs4(), i);
insertParts(string2, i);
}
}
// insert the partial matches
for (int i = 0; i < sourceModel()->rowCount(); i++) {
auto insertParts = [i, this](const QString &str) {
if (str.isEmpty())
return;
QTextBoundaryFinder finder(QTextBoundaryFinder::BoundaryType::Word, str);
finder.toStart();
do {
auto start = finder.position();
finder.toNextBoundary();
auto end = finder.position();
auto ref = str.midRef(start, end - start).trimmed();
if (!ref.isEmpty())
trie_.insert(ref.toUcs4(), i);
} while (finder.position() < str.size());
};
insertParts(sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
.toString()
.toLower());
insertParts(sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
.toString()
.toLower());
}
const auto end_at = std::chrono::steady_clock::now();
const auto build_time = std::chrono::duration<double, std::milli>(end_at - start_at);
nhlog::ui()->debug("CompletionProxyModel: build trie: {} ms", build_time.count());
// initialize default mapping
mapping.resize(std::min(max_completions_, static_cast<size_t>(model->rowCount())));
std::iota(mapping.begin(), mapping.end(), 0);
connect(
this,
......
......@@ -9,12 +9,19 @@
#include <QAbstractProxyModel>
enum class ElementRank
{
first,
second
};
template<typename Key, typename Value>
struct trie
{
std::vector<Value> values;
std::map<Key, trie> next;
template<ElementRank r>
void insert(const QVector<Key> &keys, const Value &v)
{
auto t = this;
......@@ -22,7 +29,11 @@ struct trie
t = &t->next[k];
}
t->values.push_back(v);
if constexpr (r == ElementRank::first) {
t->values.insert(t->values.begin(), v);
} else if constexpr (r == ElementRank::second) {
t->values.push_back(v);
}
}
std::vector<Value> valuesAndSubvalues(size_t limit = -1) const
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment