#include "event_filter.h" #include #include #include 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; }