summary refs log tree commit diff
path: root/src/CompletionProxyModel.h
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-11-24 02:35:38 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2020-11-25 19:05:12 +0100
commit29625ae25307aa6746df90cdecc208adc2c36ccb (patch)
tree41da3ba69577ab9b8a83acb4da66ef235dd2c562 /src/CompletionProxyModel.h
parentFix mimetype of media messages (diff)
downloadnheko-29625ae25307aa6746df90cdecc208adc2c36ccb.tar.xz
Fix some issues with completer
Diffstat (limited to '')
-rw-r--r--src/CompletionProxyModel.h89
1 files changed, 77 insertions, 12 deletions
diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h
index fa22c61e..ba28e84c 100644
--- a/src/CompletionProxyModel.h
+++ b/src/CompletionProxyModel.h
@@ -43,29 +43,94 @@ struct trie
                                 return ret;
                         else {
                                 auto temp = t.valuesAndSubvalues(limit - ret.size());
-                                ret.insert(ret.end(), temp.begin(), temp.end());
+                                for (auto &&v : temp) {
+                                        if (ret.size() >= limit)
+                                                return ret;
+
+                                        if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
+                                                ret.push_back(std::move(v));
+                                        }
+                                }
                         }
                 }
 
                 return ret;
         }
 
-        std::vector<Value> search(const QVector<Key> &keys, size_t limit) const
+        std::vector<Value> search(const QVector<Key> &keys,
+                                  size_t limit,
+                                  size_t max_distance = 2) const
         {
                 std::vector<Value> ret;
-                auto t = this;
-                int i  = 0;
-                for (; i < (int)keys.size(); i++) {
-                        if (auto e = t->next.find(keys[i]); e != t->next.end()) {
-                                t = &e->second;
-                        } else {
-                                t = nullptr;
-                                break;
+                if (!limit)
+                        return ret;
+
+                auto append = [&ret, limit](std::vector<Value> &&in) {
+                        for (auto &&v : in) {
+                                if (ret.size() >= limit)
+                                        return;
+
+                                if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
+                                        ret.push_back(std::move(v));
+                                }
+                        }
+                };
+
+                {
+                        auto t = this;
+                        int i  = 0;
+                        for (; i < (int)keys.size(); i++) {
+                                if (auto e = t->next.find(keys[i]); e != t->next.end()) {
+                                        t = &e->second;
+                                } else {
+                                        t = nullptr;
+                                        break;
+                                }
+                        }
+
+                        if (t) {
+                                ret = t->valuesAndSubvalues(limit);
                         }
                 }
 
-                if (t) {
-                        ret = t->valuesAndSubvalues(limit);
+                if (max_distance && keys.size() < static_cast<int>(limit) && keys.size() > 1) {
+                        max_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 - ret.size()) * 2, max_distance));
+                                }
+                        }
+
+                        // delete character case
+                        append(this->search(keys.mid(1), (limit - ret.size()) * 2, max_distance));
+
+                        // substitute and insert cases
+                        for (const auto &[k, t] : this->next) {
+                                if (k == keys[0] || ret.size() >= limit)
+                                        break;
+
+                                // substitute
+                                append(this->search(keys.mid(1), limit - ret.size(), max_distance));
+
+                                if (ret.size() >= limit)
+                                        break;
+
+                                // insert
+                                append(this->search(keys, limit - ret.size(), max_distance));
+                        }
                 }
 
                 return ret;