summaryrefslogtreecommitdiff
path: root/event_filter.cpp
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.si>2021-09-05 21:16:46 +0200
committerTimotej Lazar <timotej.lazar@araneo.si>2021-09-16 20:33:33 +0200
commit8d44150598a4e04a751b7df0d8c91ea29099e10e (patch)
tree7ff80ba2ea06bd8fa7b1bd0b61298cf86c0f3b85 /event_filter.cpp
parentcb76fedcbc8e419e2b945baa56ac3f986a9e79a3 (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.cpp79
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;
+}