From 7d6bd67615ad1e5d696fb1572308934314d7fb67 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 9 Apr 2021 17:20:07 +0200 Subject: [PATCH] Improve sorting a bit and fix some bugs in edge cases makes nheko appear at the top, if you search for it as well as TWIM match the twim room --- src/CompletionProxyModel.cpp | 5 +- src/CompletionProxyModel.h | 88 +++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/CompletionProxyModel.cpp b/src/CompletionProxyModel.cpp index 45b44fca..2341c292 100644 --- a/src/CompletionProxyModel.cpp +++ b/src/CompletionProxyModel.cpp @@ -28,12 +28,15 @@ CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model, ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole) .toString() .toLower(); - trie_.insert(string1.toUcs4(), i); + if (!string1.isEmpty()) + trie_.insert(string1.toUcs4(), i); auto string2 = sourceModel() ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) .toString() .toLower(); + if (!string2.isEmpty()) + trie_.insert(string2.toUcs4(), i); } // insert the partial matches diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index 5d3ae152..f19e4d93 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -59,7 +59,7 @@ struct trie std::vector search(const QVector &keys, //< TODO(Nico): replace this with a span size_t result_count_limit, - size_t max_edit_distance = 2) const + size_t max_edit_distance_ = 2) const { std::vector ret; if (!result_count_limit) @@ -79,52 +79,66 @@ struct trie } }; - if (auto e = this->next.find(keys[0]); e != this->next.end()) { - append( - e->second.search(keys.mid(1), result_count_limit, max_edit_distance)); - } + auto limit = [&ret, result_count_limit] { + return std::min(result_count_limit, (result_count_limit - ret.size()) * 2); + }; - if (max_edit_distance && ret.size() < result_count_limit) { - max_edit_distance -= 1; - - // swap chars case - if (keys.size() >= 2) { - auto t = this; - for (int i = 1; i >= 0; i--) { - if (auto e = t->next.find(keys[i]); e != t->next.end()) { - t = &e->second; - } else { - t = nullptr; - break; + // Try first exact matches, then with maximum errors + for (size_t max_edit_distance = 0; + max_edit_distance <= max_edit_distance_ && ret.size() < result_count_limit; + max_edit_distance += 1) { + if (max_edit_distance && ret.size() < result_count_limit) { + max_edit_distance -= 1; + + // swap chars case + if (keys.size() >= 2) { + auto t = this; + for (int i = 1; i >= 0; i--) { + if (auto e = t->next.find(keys[i]); + e != t->next.end()) { + t = &e->second; + } else { + t = nullptr; + break; + } + } + + if (t) { + append(t->search( + keys.mid(2), limit(), max_edit_distance)); } } - if (t) { - append(t->search(keys.mid(2), - (result_count_limit - ret.size()) * 2, - max_edit_distance)); + // insert case + for (const auto &[k, t] : this->next) { + if (k == keys[0]) + continue; + if (ret.size() >= limit()) + break; + + // insert + append(t.search(keys, limit(), max_edit_distance)); } - } - // delete character case - append(this->search( - keys.mid(1), (result_count_limit - ret.size()) * 2, max_edit_distance)); + // delete character case + append(this->search(keys.mid(1), limit(), max_edit_distance)); - // substitute and insert cases - for (const auto &[k, t] : this->next) { - if (k == keys[0] || ret.size() >= result_count_limit) - break; + // substitute case + for (const auto &[k, t] : this->next) { + if (k == keys[0]) + continue; + if (ret.size() >= limit()) + break; - // substitute - append(t.search( - keys.mid(1), result_count_limit - ret.size(), max_edit_distance)); + // substitute + append(t.search(keys.mid(1), limit(), max_edit_distance)); + } - if (ret.size() >= result_count_limit) - break; + max_edit_distance += 1; + } - // insert - append(t.search( - keys, result_count_limit - ret.size(), max_edit_distance)); + if (auto e = this->next.find(keys[0]); e != this->next.end()) { + append(e->second.search(keys.mid(1), limit(), max_edit_distance)); } }