diff options
| author | Timotej Lazar <timotej.lazar@araneo.si> | 2021-09-05 21:16:46 +0200 |
|---|---|---|
| committer | Timotej Lazar <timotej.lazar@araneo.si> | 2021-09-16 20:33:33 +0200 |
| commit | 8d44150598a4e04a751b7df0d8c91ea29099e10e (patch) | |
| tree | 7ff80ba2ea06bd8fa7b1bd0b61298cf86c0f3b85 /event_filter.cpp | |
| parent | cb76fedcbc8e419e2b945baa56ac3f986a9e79a3 (diff) | |
Implement filter
Add a proxy model class with filter logic, and use it as the model for
events ListView.
Diffstat (limited to 'event_filter.cpp')
| -rw-r--r-- | event_filter.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/event_filter.cpp b/event_filter.cpp new file mode 100644 index 0000000..d3f5e17 --- /dev/null +++ b/event_filter.cpp @@ -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; +} |
