Updates to EntrySearcher

* Only search custom named attributes
* Search attribute values in addition to keys
* Optimize search process
This commit is contained in:
Jonathan White 2019-02-22 17:17:51 -05:00
parent 5cf50d9fae
commit d0d1b25e5c
5 changed files with 48 additions and 21 deletions

View File

@ -67,6 +67,15 @@ QString EntryAttributes::value(const QString& key) const
return m_attributes.value(key); return m_attributes.value(key);
} }
QList<QString> EntryAttributes::values(const QList<QString>& keys) const
{
QList<QString> values;
for (const QString& key : keys) {
values.append(m_attributes.value(key));
}
return values;
}
bool EntryAttributes::contains(const QString& key) const bool EntryAttributes::contains(const QString& key) const
{ {
return m_attributes.contains(key); return m_attributes.contains(key);

View File

@ -36,6 +36,7 @@ public:
bool hasKey(const QString& key) const; bool hasKey(const QString& key) const;
QList<QString> customKeys() const; QList<QString> customKeys() const;
QString value(const QString& key) const; QString value(const QString& key) const;
QList<QString> values(const QList<QString>& keys) const;
bool contains(const QString& key) const; bool contains(const QString& key) const;
bool containsValue(const QString& value) const; bool containsValue(const QString& value) const;
bool isProtected(const QString& key) const; bool isProtected(const QString& key) const;

View File

@ -32,21 +32,38 @@ QList<Entry*> EntrySearcher::search(const QString& searchString, const Group* ba
{ {
Q_ASSERT(baseGroup); Q_ASSERT(baseGroup);
parseSearchTerms(searchString);
return repeat(baseGroup, forceSearch);
}
QList<Entry*> EntrySearcher::repeat(const Group* baseGroup, bool forceSearch)
{
Q_ASSERT(baseGroup);
QList<Entry*> results; QList<Entry*> results;
for (const auto group : baseGroup->groupsRecursive(true)) { for (const auto group : baseGroup->groupsRecursive(true)) {
if (forceSearch || group->resolveSearchingEnabled()) { if (forceSearch || group->resolveSearchingEnabled()) {
results.append(searchEntries(searchString, group->entries())); for (auto* entry : group->entries()) {
if (searchEntryImpl(entry)) {
results.append(entry);
}
}
} }
} }
return results; return results;
} }
QList<Entry*> EntrySearcher::searchEntries(const QString& searchString, const QList<Entry*>& entries) QList<Entry*> EntrySearcher::searchEntries(const QString& searchString, const QList<Entry*>& entries)
{
parseSearchTerms(searchString);
return repeatEntries(entries);
}
QList<Entry*> EntrySearcher::repeatEntries(const QList<Entry*>& entries)
{ {
QList<Entry*> results; QList<Entry*> results;
for (Entry* entry : entries) { for (auto* entry : entries) {
if (searchEntryImpl(searchString, entry)) { if (searchEntryImpl(entry)) {
results.append(entry); results.append(entry);
} }
} }
@ -63,16 +80,15 @@ bool EntrySearcher::isCaseSensitive()
return m_caseSensitive; return m_caseSensitive;
} }
bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry) bool EntrySearcher::searchEntryImpl(Entry* entry)
{ {
// Pre-load in case they are needed // 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()); auto attachments = QStringList(entry->attachments()->keys());
bool found; bool found;
auto searchTerms = parseSearchTerms(searchString); for (const auto& term : m_searchTerms) {
for (const auto& term : searchTerms) {
switch (term->field) { switch (term->field) {
case Field::Title: case Field::Title:
found = term->regex.match(entry->resolvePlaceholder(entry->title())).hasMatch(); found = term->regex.match(entry->resolvePlaceholder(entry->title())).hasMatch();
@ -112,10 +128,9 @@ bool EntrySearcher::searchEntryImpl(const QString& searchString, Entry* entry)
return true; return true;
} }
QList<QSharedPointer<EntrySearcher::SearchTerm>> EntrySearcher::parseSearchTerms(const QString& searchString) void EntrySearcher::parseSearchTerms(const QString& searchString)
{ {
auto terms = QList<QSharedPointer<SearchTerm>>(); m_searchTerms.clear();
auto results = m_termParser.globalMatch(searchString); auto results = m_termParser.globalMatch(searchString);
while (results.hasNext()) { while (results.hasNext()) {
auto result = results.next(); auto result = results.next();
@ -165,8 +180,6 @@ QList<QSharedPointer<EntrySearcher::SearchTerm>> EntrySearcher::parseSearchTerms
} }
} }
terms.append(term); m_searchTerms.append(term);
} }
return terms;
} }

View File

@ -31,14 +31,15 @@ public:
explicit EntrySearcher(bool caseSensitive = false); explicit EntrySearcher(bool caseSensitive = false);
QList<Entry*> search(const QString& searchString, const Group* baseGroup, bool forceSearch = false); QList<Entry*> search(const QString& searchString, const Group* baseGroup, bool forceSearch = false);
QList<Entry*> repeat(const Group* baseGroup, bool forceSearch = false);
QList<Entry*> searchEntries(const QString& searchString, const QList<Entry*>& entries); QList<Entry*> searchEntries(const QString& searchString, const QList<Entry*>& entries);
QList<Entry*> repeatEntries(const QList<Entry*>& entries);
void setCaseSensitive(bool state); void setCaseSensitive(bool state);
bool isCaseSensitive(); bool isCaseSensitive();
private: private:
bool searchEntryImpl(const QString& searchString, Entry* entry);
enum class Field enum class Field
{ {
Undefined, Undefined,
@ -59,10 +60,12 @@ private:
bool exclude; bool exclude;
}; };
QList<QSharedPointer<SearchTerm>> parseSearchTerms(const QString& searchString); bool searchEntryImpl(Entry* entry);
void parseSearchTerms(const QString& searchString);
bool m_caseSensitive; bool m_caseSensitive;
QRegularExpression m_termParser; QRegularExpression m_termParser;
QList<QSharedPointer<SearchTerm>> m_searchTerms;
friend class TestEntrySearcher; friend class TestEntrySearcher;
}; };

View File

@ -177,8 +177,8 @@ void TestEntrySearcher::testAllAttributesAreSearched()
void TestEntrySearcher::testSearchTermParser() void TestEntrySearcher::testSearchTermParser()
{ {
// Test standard search terms // 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); QCOMPARE(terms.length(), 5);
@ -200,7 +200,8 @@ void TestEntrySearcher::testSearchTermParser()
QCOMPARE(terms[4]->word, QString("noquote")); QCOMPARE(terms[4]->word, QString("noquote"));
// Test wildcard and regex search terms // 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); QCOMPARE(terms.length(), 2);