fuzbal/event_filter.cpp
Timotej Lazar ab472b748d
Reduce C++ fancyness
GCC 5.5 don’t like it. Revert once MXE catches up. Or not.
2021-09-16 21:54:22 +02:00

81 lines
2.1 KiB
C++

#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+"})) {
const int split = s.indexOf(":");
if (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 = kv->first;
const auto& fieldValue = kv->second;
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;
}