diff --git a/src/core/EntryAttributes.cpp b/src/core/EntryAttributes.cpp index bcc08f0f..80067c56 100644 --- a/src/core/EntryAttributes.cpp +++ b/src/core/EntryAttributes.cpp @@ -67,6 +67,15 @@ QString EntryAttributes::value(const QString& key) const return m_attributes.value(key); } +QList EntryAttributes::values(const QList& keys) const +{ + QList values; + for (const QString& key : keys) { + values.append(m_attributes.value(key)); + } + return values; +} + bool EntryAttributes::contains(const QString& key) const { return m_attributes.contains(key); diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h index fdae8a62..2cba13c6 100644 --- a/src/core/EntryAttributes.h +++ b/src/core/EntryAttributes.h @@ -36,6 +36,7 @@ public: bool hasKey(const QString& key) const; QList customKeys() const; QString value(const QString& key) const; + QList values(const QList& keys) const; bool contains(const QString& key) const; bool containsValue(const QString& value) const; bool isProtected(const QString& key) const; diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp index a639afd8..186a4e16 100644 --- a/src/core/EntrySearcher.cpp +++ b/src/core/EntrySearcher.cpp @@ -32,21 +32,38 @@ QList EntrySearcher::search(const QString& searchString, const Group* ba { Q_ASSERT(baseGroup); + parseSearchTerms(searchString); + return repeat(baseGroup, forceSearch); +} + +QList EntrySearcher::repeat(const Group* baseGroup, bool forceSearch) +{ + Q_ASSERT(baseGroup); + QList results; for (const auto group : baseGroup->groupsRecursive(true)) { if (forceSearch || group->resolveSearchingEnabled()) { - results.append(searchEntries(searchString, group->entries())); + for (auto* entry : group->entries()) { + if (searchEntryImpl(entry)) { + results.append(entry); + } + } } } - return results; } QList EntrySearcher::searchEntries(const QString& searchString, const QList& entries) +{ + parseSearchTerms(searchString); + return repeatEntries(entries); +} + +QList EntrySearcher::repeatEntries(const QList& entries) { QList results; - for (Entry* entry : entries) { - if (searchEntryImpl(searchString, entry)) { + for (auto* entry : entries) { + if (searchEntryImpl(entry)) { results.append(entry); } } @@ -63,16 +80,15 @@ bool EntrySearcher::isCaseSensitive() return m_caseSensitive; } -bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry) +bool EntrySearcher::searchEntryImpl(Entry* entry) { // Pre-load in case they are needed - auto attributes = QStringList(entry->attributes()->keys()); + auto attributes_keys = entry->attributes()->customKeys(); + auto attributes = QStringList(attributes_keys + entry->attributes()->values(attributes_keys)); auto attachments = QStringList(entry->attachments()->keys()); bool found; - auto searchTerms = parseSearchTerms(searchString); - - for (const auto& term : searchTerms) { + for (const auto& term : m_searchTerms) { switch (term->field) { case Field::Title: found = term->regex.match(entry->resolvePlaceholder(entry->title())).hasMatch(); @@ -112,10 +128,9 @@ bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry) return true; } -QList> EntrySearcher::parseSearchTerms(const QString& searchString) +void EntrySearcher::parseSearchTerms(const QString& searchString) { - auto terms = QList>(); - + m_searchTerms.clear(); auto results = m_termParser.globalMatch(searchString); while (results.hasNext()) { auto result = results.next(); @@ -165,8 +180,6 @@ QList> EntrySearcher::parseSearchTerms } } - terms.append(term); + m_searchTerms.append(term); } - - return terms; } diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h index d5a9951f..153a0612 100644 --- a/src/core/EntrySearcher.h +++ b/src/core/EntrySearcher.h @@ -31,14 +31,15 @@ public: explicit EntrySearcher(bool caseSensitive = false); QList search(const QString& searchString, const Group* baseGroup, bool forceSearch = false); + QList repeat(const Group* baseGroup, bool forceSearch = false); + QList searchEntries(const QString& searchString, const QList& entries); + QList repeatEntries(const QList& entries); void setCaseSensitive(bool state); bool isCaseSensitive(); private: - bool searchEntryImpl(const QString& searchString, Entry* entry); - enum class Field { Undefined, @@ -59,10 +60,12 @@ private: bool exclude; }; - QList> parseSearchTerms(const QString& searchString); + bool searchEntryImpl(Entry* entry); + void parseSearchTerms(const QString& searchString); bool m_caseSensitive; QRegularExpression m_termParser; + QList> m_searchTerms; friend class TestEntrySearcher; }; diff --git a/tests/TestEntrySearcher.cpp b/tests/TestEntrySearcher.cpp index 8128dd36..e949b97b 100644 --- a/tests/TestEntrySearcher.cpp +++ b/tests/TestEntrySearcher.cpp @@ -177,8 +177,8 @@ void TestEntrySearcher::testAllAttributesAreSearched() void TestEntrySearcher::testSearchTermParser() { // Test standard search terms - auto terms = - m_entrySearcher.parseSearchTerms("-test \"quoted \\\"string\\\"\" user:user pass:\"test me\" noquote "); + m_entrySearcher.parseSearchTerms("-test \"quoted \\\"string\\\"\" user:user pass:\"test me\" noquote "); + auto terms = m_entrySearcher.m_searchTerms; QCOMPARE(terms.length(), 5); @@ -200,7 +200,8 @@ void TestEntrySearcher::testSearchTermParser() QCOMPARE(terms[4]->word, QString("noquote")); // Test wildcard and regex search terms - terms = m_entrySearcher.parseSearchTerms("+url:*.google.com *user:\\d+\\w{2}"); + m_entrySearcher.parseSearchTerms("+url:*.google.com *user:\\d+\\w{2}"); + terms = m_entrySearcher.m_searchTerms; QCOMPARE(terms.length(), 2);