Merge pull request #1126 from nenomius/master

Do less work when building completion trie
This commit is contained in:
DeepBlueV7.X 2022-07-23 13:00:11 +02:00 committed by GitHub
commit 87365c4b5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 35 deletions

View File

@ -22,54 +22,53 @@ CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
{ {
setSourceModel(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++) { for (int i = 0; i < sourceModel()->rowCount(); i++) {
if (static_cast<size_t>(i) < max_completions_) // full texts are ranked first and partial matches second
mapping.push_back(i); // that way when searching full texts will be first in result list
auto string1 = sourceModel() auto string1 = sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole) ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
.toString() .toString()
.toLower(); .toLower();
if (!string1.isEmpty()) if (!string1.isEmpty()) {
trie_.insert(string1.toUcs4(), i); trie_.insert<ElementRank::first>(string1.toUcs4(), i);
insertParts(string1, i);
}
auto string2 = sourceModel() auto string2 = sourceModel()
->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
.toString() .toString()
.toLower(); .toLower();
if (!string2.isEmpty()) if (!string2.isEmpty()) {
trie_.insert(string2.toUcs4(), i); trie_.insert<ElementRank::first>(string2.toUcs4(), i);
insertParts(string2, i);
}
} }
// insert the partial matches const auto end_at = std::chrono::steady_clock::now();
for (int i = 0; i < sourceModel()->rowCount(); i++) { const auto build_time = std::chrono::duration<double, std::milli>(end_at - start_at);
auto insertParts = [i, this](const QString &str) { nhlog::ui()->debug("CompletionProxyModel: build trie: {} ms", build_time.count());
if (str.isEmpty())
return;
QTextBoundaryFinder finder(QTextBoundaryFinder::BoundaryType::Word, str); // initialize default mapping
finder.toStart(); mapping.resize(std::min(max_completions_, static_cast<size_t>(model->rowCount())));
do { std::iota(mapping.begin(), mapping.end(), 0);
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());
}
connect( connect(
this, this,

View File

@ -9,12 +9,19 @@
#include <QAbstractProxyModel> #include <QAbstractProxyModel>
enum class ElementRank
{
first,
second
};
template<typename Key, typename Value> template<typename Key, typename Value>
struct trie struct trie
{ {
std::vector<Value> values; std::vector<Value> values;
std::map<Key, trie> next; std::map<Key, trie> next;
template<ElementRank r>
void insert(const QVector<Key> &keys, const Value &v) void insert(const QVector<Key> &keys, const Value &v)
{ {
auto t = this; auto t = this;
@ -22,7 +29,11 @@ struct trie
t = &t->next[k]; 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 std::vector<Value> valuesAndSubvalues(size_t limit = -1) const