Implement filter
Add a proxy model class with filter logic, and use it as the model for events ListView.
This commit is contained in:
parent
cb76fedcbc
commit
8d44150598
6 changed files with 144 additions and 12 deletions
79
event_filter.cpp
Normal file
79
event_filter.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "event_filter.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QMetaType>
|
||||
#include <QRegularExpression>
|
||||
|
||||
void EventFilter::setFilter(const QString& text)
|
||||
{
|
||||
filters.clear();
|
||||
if (!text.isEmpty()) {
|
||||
for (const auto &s : text.split(QRegularExpression{"\\s+"})) {
|
||||
if (const int split = s.indexOf(":"); split == -1)
|
||||
filters.append({"", s.trimmed()});
|
||||
else
|
||||
filters.append({s.left(split).trimmed(), s.mid(split+1).trimmed()});
|
||||
}
|
||||
}
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool EventFilter::remove(int row)
|
||||
{
|
||||
return removeRows(row, 1);
|
||||
}
|
||||
|
||||
// Check if any of the given values match name: value.
|
||||
static bool matches(const QVariantMap& values, const QString& name, const QString& value)
|
||||
{
|
||||
for (auto kv = values.constKeyValueBegin(); kv != values.constKeyValueEnd(); kv++) {
|
||||
const auto& [fieldName, fieldValue] = *kv;
|
||||
if (!name.isEmpty() && !fieldName.startsWith(name))
|
||||
continue;
|
||||
|
||||
switch (fieldValue.type()) {
|
||||
case QMetaType::QString:
|
||||
// Prepend = to value for exact match.
|
||||
if (value.startsWith("=")) {
|
||||
if (fieldValue.toString() == value.mid(1))
|
||||
return true;
|
||||
} else {
|
||||
if (fieldValue.toString().contains(value))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case QMetaType::Bool:
|
||||
// Prepend ! to value for inverted match.
|
||||
if (value.startsWith("!")) {
|
||||
if (fieldName.startsWith(value.mid(1)) && !fieldValue.toBool())
|
||||
return true;
|
||||
} else {
|
||||
if (fieldName.startsWith(value) && fieldValue.toBool())
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
|
||||
{
|
||||
const auto& model = sourceModel();
|
||||
const auto& index = model->index(sourceRow, 0, sourceParent);
|
||||
|
||||
const auto& roles = model->roleNames();
|
||||
const auto& tag = model->data(index, roles.key("tag")).toString();
|
||||
const auto& values = model->data(index, roles.key("values")).toMap();
|
||||
|
||||
for (const auto& filter : filters) {
|
||||
if (filter.first.isEmpty() && tag.startsWith(filter.second))
|
||||
continue;
|
||||
if (matches(values, filter.first, filter.second))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue