Implement event model in C++
Filtering events in JS is too slow with >20,000 events. This moves the event data model into C++.
This commit is contained in:
parent
e9b70c585c
commit
cb76fedcbc
14 changed files with 375 additions and 342 deletions
141
event_list.cpp
Normal file
141
event_list.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include "event_list.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJSValue>
|
||||
|
||||
Qt::ItemFlags EventList::flags(const QModelIndex&) const
|
||||
{
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> EventList::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles{
|
||||
{Role::Time, "time"},
|
||||
{Role::Tag, "tag"},
|
||||
{Role::Values, "values"},
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
|
||||
int EventList::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return events.size();
|
||||
}
|
||||
|
||||
QVariant EventList::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
const auto& event = events[index.row()];
|
||||
switch (role) {
|
||||
case Role::Time:
|
||||
return event.time;
|
||||
case Role::Tag:
|
||||
return event.tag;
|
||||
case Role::Values:
|
||||
return event.values;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool EventList::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
auto& event = events[index.row()];
|
||||
switch (role) {
|
||||
case Role::Time:
|
||||
event.time = value.toLongLong();
|
||||
break;
|
||||
case Role::Tag:
|
||||
event.tag = value.toString();
|
||||
break;
|
||||
case Role::Values:
|
||||
event.values = value.value<QJSValue>().toVariant().toMap();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
|
||||
int EventList::insert(const int time)
|
||||
{
|
||||
int row = time == -1 ? rowCount() : find(time);
|
||||
beginInsertRows(QModelIndex{}, row, row);
|
||||
events.insert(row, {time});
|
||||
endInsertRows();
|
||||
return row;
|
||||
}
|
||||
|
||||
bool EventList::removeRows(int row, int count, const QModelIndex&)
|
||||
{
|
||||
beginRemoveRows({}, row, row + count - 1);
|
||||
while (row < events.size() && count-- > 0)
|
||||
events.removeAt(row);
|
||||
endRemoveRows();
|
||||
return count == -1;
|
||||
}
|
||||
|
||||
void EventList::load(const QJsonObject& json)
|
||||
{
|
||||
const auto& jsonTags = json["tags"].toArray();
|
||||
if (!jsonTags.isEmpty()) {
|
||||
tags = {};
|
||||
tagsOrder.clear();
|
||||
for (int i = 0; i < jsonTags.size(); i++) {
|
||||
const auto name = jsonTags[i]["tag"].toString();
|
||||
tags[name] = jsonTags[i].toObject();
|
||||
tagsOrder.append(name);
|
||||
}
|
||||
emit tagsChanged();
|
||||
}
|
||||
|
||||
const auto& jsonEvents = json["events"].toArray();
|
||||
if (!jsonEvents.isEmpty()) {
|
||||
beginResetModel();
|
||||
events.clear();
|
||||
for (int i = 0; i < jsonEvents.size(); i++) {
|
||||
auto event = jsonEvents[i].toObject().toVariantMap();
|
||||
events.append({
|
||||
event["time"].toLongLong(),
|
||||
event["tag"].toString(),
|
||||
event[event.contains("values") ? "values" : "fields"].toMap(),
|
||||
});
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject EventList::save() const
|
||||
{
|
||||
QJsonArray jsonEvents;
|
||||
for (const auto& event : events) {
|
||||
jsonEvents.append(QJsonObject{
|
||||
{"time", event.time},
|
||||
{"tag", event.tag},
|
||||
{"values", QJsonObject::fromVariantMap(event.values)}
|
||||
});
|
||||
}
|
||||
|
||||
QJsonArray jsonTags;
|
||||
for (int i = 0; i < tagsOrder.size(); i++)
|
||||
jsonTags.append(tags[tagsOrder[i]].toObject());
|
||||
|
||||
return {{"tags", jsonTags}, {"events", jsonEvents}};
|
||||
}
|
||||
|
||||
// Return the index of the last event not later than given time.
|
||||
// Assumes events are sorted by time.
|
||||
int EventList::find(long long time) const
|
||||
{
|
||||
int low = 0;
|
||||
int high = events.size() - 1;
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
if (events[mid].time <= time)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid - 1;
|
||||
}
|
||||
return low;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue