summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authornenomius <nenomius@protonmail.com>2022-07-23 00:52:11 +0300
committernenomius <nenomius@protonmail.com>2022-07-23 13:33:36 +0300
commit5e99bace905663bf23e00f7107d09f27b1a8acc0 (patch)
tree8a8e1d4358d312ad7625bf096a9e7d546a587123 /src
parentTranslated using Weblate (Polish) (diff)
downloadnheko-5e99bace905663bf23e00f7107d09f27b1a8acc0.tar.xz
Do less work when building completion trie
Convert to lower case only once per string.
Diffstat (limited to 'src')
-rw-r--r--src/CompletionProxyModel.cpp69
-rw-r--r--src/CompletionProxyModel.h13
2 files changed, 46 insertions, 36 deletions
diff --git a/src/CompletionProxyModel.cpp b/src/CompletionProxyModel.cpp

index 07ecdf72..5712cd30 100644 --- a/src/CompletionProxyModel.cpp +++ b/src/CompletionProxyModel.cpp
@@ -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, diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h
index 78c7ea5f..e4a1b9cd 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h
@@ -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