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);
}
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
{
return m_attributes.contains(key);

View File

@ -36,6 +36,7 @@ public:
bool hasKey(const QString& key) const;
QList<QString> customKeys() const;
QString value(const QString& key) const;
QList<QString> values(const QList<QString>& keys) const;
bool contains(const QString& key) const;
bool containsValue(const QString& value) 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);
parseSearchTerms(searchString);
return repeat(baseGroup, forceSearch);
}
QList<Entry*> EntrySearcher::repeat(const Group* baseGroup, bool forceSearch)
{
Q_ASSERT(baseGroup);
QList<Entry*> 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<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;
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<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);
while (results.hasNext()) {
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);
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*> repeatEntries(const QList<Entry*>& 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<QSharedPointer<SearchTerm>> parseSearchTerms(const QString& searchString);
bool searchEntryImpl(Entry* entry);
void parseSearchTerms(const QString& searchString);
bool m_caseSensitive;
QRegularExpression m_termParser;
QList<QSharedPointer<SearchTerm>> m_searchTerms;
friend class TestEntrySearcher;
};

View File

@ -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);