Add a proxy model class with filter logic, and use it as the model for events ListView.
141 lines
3.1 KiB
C++
141 lines
3.1 KiB
C++
#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 QString& tag, const int time)
|
|
{
|
|
int row = time == -1 ? rowCount() : find(time);
|
|
beginInsertRows(QModelIndex{}, row, row);
|
|
events.insert(row, {time, tag});
|
|
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;
|
|
}
|