improve statelog view a bit
This commit is contained in:
parent
fe27f94ba1
commit
1b51a6e4f4
@ -25,6 +25,7 @@
|
|||||||
#include "types/stateevaluator.h"
|
#include "types/stateevaluator.h"
|
||||||
#include "types/stateevaluators.h"
|
#include "types/stateevaluators.h"
|
||||||
#include "models/logsmodel.h"
|
#include "models/logsmodel.h"
|
||||||
|
#include "models/logsmodelng.h"
|
||||||
#include "models/valuelogsproxymodel.h"
|
#include "models/valuelogsproxymodel.h"
|
||||||
#include "models/eventdescriptorparamsfiltermodel.h"
|
#include "models/eventdescriptorparamsfiltermodel.h"
|
||||||
#include "basicconfiguration.h"
|
#include "basicconfiguration.h"
|
||||||
@ -122,6 +123,7 @@ void registerQmlTypes() {
|
|||||||
qmlRegisterType<EventDescriptorParamsFilterModel>(uri, 1, 0, "EventDescriptorParamsFilterModel");
|
qmlRegisterType<EventDescriptorParamsFilterModel>(uri, 1, 0, "EventDescriptorParamsFilterModel");
|
||||||
|
|
||||||
qmlRegisterType<LogsModel>(uri, 1, 0, "LogsModel");
|
qmlRegisterType<LogsModel>(uri, 1, 0, "LogsModel");
|
||||||
|
qmlRegisterType<LogsModelNg>(uri, 1, 0, "LogsModelNg");
|
||||||
qmlRegisterType<ValueLogsProxyModel>(uri, 1, 0, "ValueLogsProxyModel");
|
qmlRegisterType<ValueLogsProxyModel>(uri, 1, 0, "ValueLogsProxyModel");
|
||||||
qmlRegisterUncreatableType<LogEntry>(uri, 1, 0, "LogEntry", "Get them from LogsModel");
|
qmlRegisterUncreatableType<LogEntry>(uri, 1, 0, "LogEntry", "Get them from LogsModel");
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@ SOURCES += \
|
|||||||
wifisetup/wirelessaccesspoints.cpp \
|
wifisetup/wirelessaccesspoints.cpp \
|
||||||
wifisetup/wirelesssetupmanager.cpp \
|
wifisetup/wirelesssetupmanager.cpp \
|
||||||
wifisetup/networkmanagercontroler.cpp \
|
wifisetup/networkmanagercontroler.cpp \
|
||||||
|
models/logsmodelng.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
engine.h \
|
engine.h \
|
||||||
@ -97,7 +98,8 @@ HEADERS += \
|
|||||||
wifisetup/wirelessaccesspoints.h \
|
wifisetup/wirelessaccesspoints.h \
|
||||||
wifisetup/wirelesssetupmanager.h \
|
wifisetup/wirelesssetupmanager.h \
|
||||||
wifisetup/networkmanagercontroler.h \
|
wifisetup/networkmanagercontroler.h \
|
||||||
libmea-core.h
|
libmea-core.h \
|
||||||
|
models/logsmodelng.h
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
target.path = /usr/lib
|
target.path = /usr/lib
|
||||||
|
|||||||
297
libmea-core/models/logsmodelng.cpp
Normal file
297
libmea-core/models/logsmodelng.cpp
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
#include "logsmodelng.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
#include "engine.h"
|
||||||
|
#include "types/logentry.h"
|
||||||
|
|
||||||
|
LogsModelNg::LogsModelNg(QObject *parent) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogsModelNg::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_list.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant LogsModelNg::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case RoleTimestamp:
|
||||||
|
return m_list.at(index.row())->timestamp();
|
||||||
|
case RoleValue:
|
||||||
|
return m_list.at(index.row())->value();
|
||||||
|
case RoleDeviceId:
|
||||||
|
return m_list.at(index.row())->deviceId();
|
||||||
|
case RoleTypeId:
|
||||||
|
return m_list.at(index.row())->typeId();
|
||||||
|
case RoleSource:
|
||||||
|
return m_list.at(index.row())->source();
|
||||||
|
case RoleLoggingEventType:
|
||||||
|
return m_list.at(index.row())->loggingEventType();
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> LogsModelNg::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(RoleTimestamp, "timestamp");
|
||||||
|
roles.insert(RoleValue, "value");
|
||||||
|
roles.insert(RoleDeviceId, "deviceId");
|
||||||
|
roles.insert(RoleTypeId, "typeId");
|
||||||
|
roles.insert(RoleSource, "source");
|
||||||
|
roles.insert(RoleLoggingEventType, "loggingEventType");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogsModelNg::busy() const
|
||||||
|
{
|
||||||
|
return m_busy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LogsModelNg::live() const
|
||||||
|
{
|
||||||
|
return m_live;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::setLive(bool live)
|
||||||
|
{
|
||||||
|
if (m_live != live) {
|
||||||
|
m_live = live;
|
||||||
|
emit liveChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LogsModelNg::deviceId() const
|
||||||
|
{
|
||||||
|
return m_deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::setDeviceId(const QString &deviceId)
|
||||||
|
{
|
||||||
|
if (m_deviceId != deviceId) {
|
||||||
|
m_deviceId = deviceId;
|
||||||
|
emit deviceIdChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LogsModelNg::typeId() const
|
||||||
|
{
|
||||||
|
return m_typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::setTypeId(const QString &typeId)
|
||||||
|
{
|
||||||
|
if (m_typeId != typeId) {
|
||||||
|
m_typeId = typeId;
|
||||||
|
emit typeIdChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime LogsModelNg::startTime() const
|
||||||
|
{
|
||||||
|
return m_startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::setStartTime(const QDateTime &startTime)
|
||||||
|
{
|
||||||
|
if (m_startTime != startTime) {
|
||||||
|
m_startTime = startTime;
|
||||||
|
emit startTimeChanged();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime LogsModelNg::endTime() const
|
||||||
|
{
|
||||||
|
return m_endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::setEndTime(const QDateTime &endTime)
|
||||||
|
{
|
||||||
|
if (m_endTime != endTime) {
|
||||||
|
m_endTime = endTime;
|
||||||
|
emit endTimeChanged();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::update()
|
||||||
|
{
|
||||||
|
if (m_busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_startTime.isNull() || m_endTime.isNull()) {
|
||||||
|
// Need both, startTime and endTime set
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentFetchStartTime = QDateTime();
|
||||||
|
m_currentFetchEndTime = QDateTime();
|
||||||
|
bool haveData = false;
|
||||||
|
for(int i = 0; i < m_fetchedPeriods.length(); i++) {
|
||||||
|
if (m_fetchedPeriods.at(i).first < m_startTime) {
|
||||||
|
if (m_fetchedPeriods.at(i).second == true) {
|
||||||
|
haveData = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).second == false) {
|
||||||
|
haveData = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).first == m_startTime) {
|
||||||
|
if (m_fetchedPeriods.at(i).second == true) {
|
||||||
|
haveData = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).second == false) {
|
||||||
|
m_currentFetchStartTime = m_startTime;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).first > m_startTime) {
|
||||||
|
if (m_fetchedPeriods.at(i).second == true) {
|
||||||
|
if (m_currentFetchStartTime.isNull()) {
|
||||||
|
m_currentFetchStartTime = m_startTime;
|
||||||
|
}
|
||||||
|
m_currentFetchEndTime = m_fetchedPeriods.at(i).first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).second == false) {
|
||||||
|
if (m_currentFetchStartTime.isNull()) {
|
||||||
|
haveData = false;
|
||||||
|
m_currentFetchStartTime = m_fetchedPeriods.at(i).first;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (haveData) {
|
||||||
|
qDebug() << "all the data is fetched";
|
||||||
|
m_busy = false;
|
||||||
|
emit busyChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_currentFetchStartTime.isNull()) {
|
||||||
|
m_currentFetchStartTime = m_startTime;
|
||||||
|
}
|
||||||
|
if (m_currentFetchEndTime.isNull()) {
|
||||||
|
m_currentFetchEndTime = m_endTime;
|
||||||
|
}
|
||||||
|
qDebug() << "Fetching from" << m_currentFetchStartTime << "to" << m_currentFetchEndTime;
|
||||||
|
|
||||||
|
m_busy = true;
|
||||||
|
emit busyChanged();
|
||||||
|
|
||||||
|
QVariantMap params;
|
||||||
|
if (!m_deviceId.isEmpty()) {
|
||||||
|
QVariantList deviceIds;
|
||||||
|
deviceIds.append(m_deviceId);
|
||||||
|
params.insert("deviceIds", deviceIds);
|
||||||
|
}
|
||||||
|
if (!m_typeId.isEmpty()) {
|
||||||
|
QVariantList typeIds;
|
||||||
|
typeIds.append(m_typeId);
|
||||||
|
params.insert("typeIds", typeIds);
|
||||||
|
}
|
||||||
|
QVariantList timeFilters;
|
||||||
|
QVariantMap timeFilter;
|
||||||
|
timeFilter.insert("startDate", m_currentFetchStartTime.toSecsSinceEpoch());
|
||||||
|
timeFilter.insert("endDate", m_currentFetchEndTime.toSecsSinceEpoch());
|
||||||
|
timeFilters.append(timeFilter);
|
||||||
|
params.insert("timeFilters", timeFilters);
|
||||||
|
Engine::instance()->jsonRpcClient()->sendCommand("Logging.GetLogEntries", params, this, "logsReply");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogsModelNg::logsReply(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
qDebug() << "logs reply";// << data;
|
||||||
|
|
||||||
|
// First update the fetched periods information
|
||||||
|
int insertIndex = -1;
|
||||||
|
bool noNeedToInsert = false;
|
||||||
|
for (int i = 0; i < m_fetchedPeriods.count(); i++) {
|
||||||
|
if (m_fetchedPeriods.at(i).first < m_currentFetchStartTime) {
|
||||||
|
// skip it
|
||||||
|
insertIndex = i+1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).first == m_currentFetchStartTime) {
|
||||||
|
if (m_fetchedPeriods.at(i).second == false) {
|
||||||
|
// Have an end marker where we start inserting. We can drop the existing end marker and just update the end marker
|
||||||
|
if (m_fetchedPeriods.count() > i+1) {
|
||||||
|
if (m_fetchedPeriods.at(i+1).first < m_currentFetchEndTime) {
|
||||||
|
qWarning() << "Overlap detected!";
|
||||||
|
} else if (m_fetchedPeriods.at(i+1).first == m_currentFetchEndTime) {
|
||||||
|
if (m_fetchedPeriods.at(i+1).second == true) {
|
||||||
|
m_fetchedPeriods.removeAt(i+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_fetchedPeriods.removeAt(i);
|
||||||
|
noNeedToInsert = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_fetchedPeriods.at(i).first > m_currentFetchStartTime) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noNeedToInsert) {
|
||||||
|
if (insertIndex == -1) {
|
||||||
|
insertIndex = 0;
|
||||||
|
}
|
||||||
|
m_fetchedPeriods.insert(insertIndex, qMakePair<QDateTime,bool>(m_currentFetchStartTime, true));
|
||||||
|
m_fetchedPeriods.insert(insertIndex+1, qMakePair<QDateTime,bool>(m_currentFetchEndTime, false));
|
||||||
|
}
|
||||||
|
qDebug() << "new fetched periods:" << m_fetchedPeriods << "insertIndex:" << insertIndex;
|
||||||
|
m_busy = false;
|
||||||
|
emit busyChanged();
|
||||||
|
|
||||||
|
|
||||||
|
QList<LogEntry*> newBlock;
|
||||||
|
QList<QVariant> logEntries = data.value("params").toMap().value("logEntries").toList();
|
||||||
|
foreach (const QVariant &logEntryVariant, logEntries) {
|
||||||
|
QVariantMap entryMap = logEntryVariant.toMap();
|
||||||
|
QDateTime timeStamp = QDateTime::fromMSecsSinceEpoch(entryMap.value("timestamp").toLongLong());
|
||||||
|
QString deviceId = entryMap.value("deviceId").toString();
|
||||||
|
QString typeId = entryMap.value("typeId").toString();
|
||||||
|
QMetaEnum sourceEnum = QMetaEnum::fromType<LogEntry::LoggingSource>();
|
||||||
|
LogEntry::LoggingSource loggingSource = (LogEntry::LoggingSource)sourceEnum.keyToValue(entryMap.value("source").toByteArray());
|
||||||
|
QMetaEnum loggingEventTypeEnum = QMetaEnum::fromType<LogEntry::LoggingEventType>();
|
||||||
|
LogEntry::LoggingEventType loggingEventType = (LogEntry::LoggingEventType)loggingEventTypeEnum.keyToValue(entryMap.value("eventType").toByteArray());
|
||||||
|
QVariant value = loggingEventType == LogEntry::LoggingEventTypeActiveChange ? entryMap.value("active").toBool() : entryMap.value("value");
|
||||||
|
LogEntry *entry = new LogEntry(timeStamp, value, deviceId, typeId, loggingSource, loggingEventType, this);
|
||||||
|
newBlock.append(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now let's find where to insert stuff in the model
|
||||||
|
if (!newBlock.isEmpty()) {
|
||||||
|
int indexToInsert = 0;
|
||||||
|
for (int i = 0; i < m_list.count(); i++) {
|
||||||
|
LogEntry *entry = m_list.at(i);
|
||||||
|
if (entry->timestamp() < newBlock.first()->timestamp()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
indexToInsert = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), indexToInsert, indexToInsert + newBlock.count() - 1);
|
||||||
|
for (int i = 0; i < newBlock.count(); i++) {
|
||||||
|
m_list.insert(indexToInsert + i, newBlock.at(i));
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
82
libmea-core/models/logsmodelng.h
Normal file
82
libmea-core/models/logsmodelng.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef LOGSMODELNG_H
|
||||||
|
#define LOGSMODELNG_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class LogEntry;
|
||||||
|
|
||||||
|
class LogsModelNg : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
|
Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
|
||||||
|
Q_PROPERTY(QString typeId READ typeId WRITE setTypeId NOTIFY typeIdChanged)
|
||||||
|
Q_PROPERTY(QDateTime startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||||
|
Q_PROPERTY(QDateTime endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles {
|
||||||
|
RoleTimestamp,
|
||||||
|
RoleValue,
|
||||||
|
RoleDeviceId,
|
||||||
|
RoleTypeId,
|
||||||
|
RoleSource,
|
||||||
|
RoleLoggingEventType
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit LogsModelNg(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
bool busy() const;
|
||||||
|
|
||||||
|
bool live() const;
|
||||||
|
void setLive(bool live);
|
||||||
|
|
||||||
|
QString deviceId() const;
|
||||||
|
void setDeviceId(const QString &deviceId);
|
||||||
|
|
||||||
|
QString typeId() const;
|
||||||
|
void setTypeId(const QString &typeId);
|
||||||
|
|
||||||
|
QDateTime startTime() const;
|
||||||
|
void setStartTime(const QDateTime &startTime);
|
||||||
|
|
||||||
|
QDateTime endTime() const;
|
||||||
|
void setEndTime(const QDateTime &endTime);
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void busyChanged();
|
||||||
|
void liveChanged();
|
||||||
|
void deviceIdChanged();
|
||||||
|
void typeIdChanged();
|
||||||
|
void countChanged();
|
||||||
|
void startTimeChanged();
|
||||||
|
void endTimeChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<LogEntry*> m_list;
|
||||||
|
|
||||||
|
bool m_busy = false;
|
||||||
|
bool m_live = false;
|
||||||
|
QString m_deviceId;
|
||||||
|
QString m_typeId;
|
||||||
|
QDateTime m_startTime;
|
||||||
|
QDateTime m_endTime;
|
||||||
|
QDateTime m_currentFetchStartTime;
|
||||||
|
QDateTime m_currentFetchEndTime;
|
||||||
|
|
||||||
|
QList<QPair<QDateTime, bool> > m_fetchedPeriods;
|
||||||
|
|
||||||
|
void update();
|
||||||
|
Q_INVOKABLE void logsReply(const QVariantMap &data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LOGSMODELNG_H
|
||||||
@ -51,7 +51,7 @@ StateType *StateTypes::getStateType(const QUuid &stateTypeId) const
|
|||||||
return stateType;
|
return stateType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StateTypes::rowCount(const QModelIndex &parent) const
|
int StateTypes::rowCount(const QModelIndex &parent) const
|
||||||
|
|||||||
@ -17,6 +17,10 @@ Item {
|
|||||||
}
|
}
|
||||||
onModelChanged: canvas.requestPaint()
|
onModelChanged: canvas.requestPaint()
|
||||||
|
|
||||||
|
readonly property var device: root.model ? Engine.deviceManager.devices.getDevice(root.model.deviceId) : null
|
||||||
|
readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||||
|
readonly property var stateType: deviceClass ? deviceClass.stateTypes.getStateType(root.model.typeId) : null
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: parent.width - 2 * app.margins
|
width: parent.width - 2 * app.margins
|
||||||
@ -41,7 +45,7 @@ Item {
|
|||||||
property int minTemp: {
|
property int minTemp: {
|
||||||
var lower = Math.floor(root.model.minimumValue - 2);
|
var lower = Math.floor(root.model.minimumValue - 2);
|
||||||
var upper = Math.ceil(root.model.maximumValue + 2);
|
var upper = Math.ceil(root.model.maximumValue + 2);
|
||||||
if (lower == undefined || upper == undefined) {
|
if (isNaN(lower) || isNaN(upper) || lower == undefined || upper == undefined) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +61,7 @@ Item {
|
|||||||
property int maxTemp: {
|
property int maxTemp: {
|
||||||
var lower = Math.floor(root.model.minimumValue - 2);
|
var lower = Math.floor(root.model.minimumValue - 2);
|
||||||
var upper = Math.ceil(root.model.maximumValue + 2);
|
var upper = Math.ceil(root.model.maximumValue + 2);
|
||||||
if (lower == undefined || upper == undefined) {
|
if (isNaN(lower) || isNaN(upper) || lower == undefined || upper == undefined) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
while ((upper - lower) % 10 != 0) {
|
while ((upper - lower) % 10 != 0) {
|
||||||
@ -70,8 +74,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property int topMargins: app.margins
|
property int topMargins: app.margins
|
||||||
property int bottomMargins: app.margins * 4
|
property int bottomMargins: app.margins
|
||||||
property int leftMargins: app.margins * 3
|
property int leftMargins: app.margins
|
||||||
property int rightMargins: app.margins
|
property int rightMargins: app.margins
|
||||||
|
|
||||||
property color gridColor: "#d0d0d0"
|
property color gridColor: "#d0d0d0"
|
||||||
@ -87,53 +91,60 @@ Item {
|
|||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
// Pixel per section
|
|
||||||
property real pps: contentHeight / sections;
|
|
||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
|
print("painting graph")
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext('2d');
|
||||||
ctx.save();
|
ctx.save();
|
||||||
|
|
||||||
ctx.reset()
|
ctx.reset()
|
||||||
|
|
||||||
ctx.translate(leftMargins, topMargins)
|
ctx.font = "" + app.smallFont + "px Ubuntu";
|
||||||
|
|
||||||
ctx.globalAlpha = 1//canvas.alpha;
|
ctx.globalAlpha = 1//canvas.alpha;
|
||||||
//ctx.fillStyle = canvas.fillStyle;
|
//ctx.fillStyle = canvas.fillStyle;
|
||||||
ctx.font = "" + app.smallFont + "px Ubuntu";
|
|
||||||
|
|
||||||
paintGrid(ctx)
|
var textSize = ctx.measureText(maxTemp);
|
||||||
enumerate(ctx)
|
var leftTextWidth = textSize.width + app.margins;
|
||||||
|
var bottomTextHeight = app.smallFont * 2 + app.margins;
|
||||||
|
var topTextHeight = app.smallFont + app.margins;
|
||||||
|
ctx.translate(leftMargins + leftTextWidth, topMargins);
|
||||||
|
var gridWidth = contentWidth - leftTextWidth;
|
||||||
|
var gridHeight = contentHeight - bottomTextHeight;
|
||||||
|
|
||||||
|
|
||||||
|
paintGrid(ctx, gridWidth, gridHeight)
|
||||||
|
enumerate(ctx, gridWidth, gridHeight)
|
||||||
|
|
||||||
if (root.mode == "bezier") {
|
if (root.mode == "bezier") {
|
||||||
paintGraph(ctx)
|
paintGraph(ctx, gridWidth, gridHeight)
|
||||||
} else {
|
} else {
|
||||||
paintBars(ctx)
|
paintBars(ctx, gridWidth, gridHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function paintGrid(ctx) {
|
function paintGrid(ctx, width, height) {
|
||||||
ctx.strokeStyle = canvas.gridColor;
|
ctx.strokeStyle = canvas.gridColor;
|
||||||
ctx.fillStyle = Material.foreground
|
ctx.fillStyle = Material.foreground
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.rect(0, 0, contentWidth, contentHeight)
|
ctx.rect(0, 0, width, height)
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
|
|
||||||
// Horizontal lines
|
// Horizontal lines
|
||||||
var tempInterval = (maxTemp - minTemp) / sections;
|
var tempInterval = (maxTemp - minTemp) / sections;
|
||||||
|
var pps = (height / sections);
|
||||||
|
|
||||||
for (var i = 0; i <= sections; i++) {
|
for (var i = 0; i <= sections; i++) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
ctx.strokeStyle = canvas.gridColor
|
ctx.strokeStyle = canvas.gridColor
|
||||||
ctx.moveTo(0, i * pps);
|
ctx.moveTo(0, i * pps);
|
||||||
ctx.lineTo(contentWidth, i * pps)
|
ctx.lineTo(width, i * pps)
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
|
|
||||||
@ -153,16 +164,17 @@ Item {
|
|||||||
ctx.strokeStyle = Material.foreground
|
ctx.strokeStyle = Material.foreground
|
||||||
ctx.fillStyle = Material.foreground
|
ctx.fillStyle = Material.foreground
|
||||||
ctx.lineWidth = 0;
|
ctx.lineWidth = 0;
|
||||||
var label = "°C"
|
print("blubb", root.stateType.unitString)
|
||||||
|
var label = root.stateType ? root.stateType.unitString : ""
|
||||||
var textSize = ctx.measureText(label)
|
var textSize = ctx.measureText(label)
|
||||||
ctx.text(label, -textSize.width - 1, -1 * pps + 5)
|
ctx.text(label, -textSize.width - app.margins, height + app.margins + app.smallFont)
|
||||||
// ctx.stroke();
|
// ctx.stroke();
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
ctx.closePath()
|
ctx.closePath()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function enumerate(ctx) {
|
function enumerate(ctx, width, height) {
|
||||||
// enumate x axis
|
// enumate x axis
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
@ -173,12 +185,12 @@ Item {
|
|||||||
|
|
||||||
var lastTextX = -1;
|
var lastTextX = -1;
|
||||||
for (var i = 0; i < model.count; i++) {
|
for (var i = 0; i < model.count; i++) {
|
||||||
var x = contentWidth / (model.count) * i;
|
var x = width / (model.count) * i;
|
||||||
if (x < lastTextX) continue;
|
if (x < lastTextX) continue;
|
||||||
|
|
||||||
var label = model.get(i).dayString
|
var label = model.get(i).dayString
|
||||||
var textSize = ctx.measureText(label)
|
var textSize = ctx.measureText(label)
|
||||||
ctx.text(label.slice(0,2).concat("."), x, contentHeight + app.smallFont + app.margins / 2)
|
ctx.text(label.slice(0,2).concat("."), x, height + app.smallFont + app.margins / 2)
|
||||||
|
|
||||||
switch (model.average) {
|
switch (model.average) {
|
||||||
case ValueLogsProxyModel.AverageQuarterHour:
|
case ValueLogsProxyModel.AverageQuarterHour:
|
||||||
@ -191,7 +203,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
textSize = ctx.measureText(label)
|
textSize = ctx.measureText(label)
|
||||||
ctx.text(label, x, contentHeight + app.smallFont * 2 + app.margins)
|
ctx.text(label, x, height + app.smallFont * 2 + app.margins)
|
||||||
lastTextX = x + textSize.width;
|
lastTextX = x + textSize.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,12 +212,13 @@ Item {
|
|||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
function paintGraph(ctx) {
|
function paintGraph(ctx, width, height) {
|
||||||
if (model.count <= 1) {
|
if (model.count <= 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempInterval = (maxTemp - minTemp) / sections;
|
var tempInterval = (maxTemp - minTemp) / sections;
|
||||||
|
var pps = (height / sections)
|
||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
@ -221,8 +234,8 @@ Item {
|
|||||||
var value = model.get(i).value;
|
var value = model.get(i).value;
|
||||||
var point = new Object();
|
var point = new Object();
|
||||||
// print("painting value", value)
|
// print("painting value", value)
|
||||||
point.x = (i == 0) ? 0 : (contentWidth / (model.count - 2) * i);
|
point.x = (i == 0) ? 0 : (width / (model.count - 2) * i);
|
||||||
point.y = contentHeight - (value - minTemp) / tempInterval * pps;
|
point.y = height - (value - minTemp) / tempInterval * pps;
|
||||||
points.push(point);
|
points.push(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +245,8 @@ Item {
|
|||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
paintBezier(ctx, points)
|
paintBezier(ctx, points)
|
||||||
ctx.lineTo(contentWidth, contentHeight);
|
ctx.lineTo(width, height);
|
||||||
ctx.lineTo(0, contentHeight);
|
ctx.lineTo(0, height);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
|
|
||||||
@ -248,7 +261,7 @@ Item {
|
|||||||
for (var i = 0; i < model.count; i++) {
|
for (var i = 0; i < model.count; i++) {
|
||||||
var dayMaxTemp = model.get(i).maxTemp;
|
var dayMaxTemp = model.get(i).maxTemp;
|
||||||
var point = new Object();
|
var point = new Object();
|
||||||
point.x = (i == 0) ? 0 : (contentWidth / (model.count - 1) * i);
|
point.x = (i == 0) ? 0 : (width / (model.count - 1) * i);
|
||||||
point.y = - (dayMaxTemp - maxTemp) / tempInterval * pps;
|
point.y = - (dayMaxTemp - maxTemp) / tempInterval * pps;
|
||||||
points.push(point);
|
points.push(point);
|
||||||
}
|
}
|
||||||
@ -312,12 +325,13 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function paintBars(ctx) {
|
function paintBars(ctx, width, height) {
|
||||||
if (model.count <= 1) {
|
if (model.count <= 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempInterval = (maxTemp - minTemp) / sections;
|
var tempInterval = (maxTemp - minTemp) / sections;
|
||||||
|
var pps = (height / sections)
|
||||||
|
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
ctx.lineWidth = 2;
|
ctx.lineWidth = 2;
|
||||||
@ -331,21 +345,21 @@ Item {
|
|||||||
for (var i = 0; i < model.count; i++) {
|
for (var i = 0; i < model.count; i++) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
var value = model.get(i).value;
|
var value = model.get(i).value;
|
||||||
var x = contentWidth / (model.count) * i;
|
var x = width / (model.count) * i;
|
||||||
var y = contentHeight - (value - minTemp) / tempInterval * pps;
|
var y = height - (value - minTemp) / tempInterval * pps;
|
||||||
|
|
||||||
var slotWidth = contentWidth / model.count
|
var slotWidth = width / model.count
|
||||||
ctx.rect(x,y, slotWidth - 5, contentHeight - y)
|
ctx.rect(x,y, slotWidth - 5, height - y)
|
||||||
ctx.fillRect(x,y, slotWidth - 5, contentHeight - y);
|
ctx.fillRect(x,y, slotWidth - 5, height - y);
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hourToX(hour) {
|
function hourToX(hour, width) {
|
||||||
var entries = root.day.count;
|
var entries = root.day.count;
|
||||||
return canvas.contentWidth / entries * hour
|
return canvas.width / entries * hour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,23 +6,12 @@ import "../components"
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var device: null
|
|
||||||
property alias typeId: logs.typeId
|
|
||||||
|
|
||||||
// %1 will be replaced with count
|
// %1 will be replaced with count
|
||||||
property string text
|
property string text
|
||||||
|
|
||||||
signal addRuleClicked(var value)
|
signal addRuleClicked(var value)
|
||||||
|
|
||||||
readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
property var logsModel: null
|
||||||
|
|
||||||
LogsModel {
|
|
||||||
id: logs
|
|
||||||
deviceId: root.device.id
|
|
||||||
live: true
|
|
||||||
Component.onCompleted: update()
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -32,7 +21,7 @@ Item {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: root.text.arg(logs.count)
|
text: root.text.arg(logsModel.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
ThinDivider {}
|
ThinDivider {}
|
||||||
@ -40,14 +29,16 @@ Item {
|
|||||||
RulesFilterModel {
|
RulesFilterModel {
|
||||||
id: rulesFilterModel
|
id: rulesFilterModel
|
||||||
rules: Engine.ruleManager.rules
|
rules: Engine.ruleManager.rules
|
||||||
filterDeviceId: root.device.id
|
filterDeviceId: root.logsModel.deviceId
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
id: listView
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
model: logs
|
model: logsModel
|
||||||
clip: true
|
clip: true
|
||||||
|
onCountChanged: positionViewAtEnd()
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
@ -87,7 +78,7 @@ Item {
|
|||||||
var rule = rulesFilterModel.get(i);
|
var rule = rulesFilterModel.get(i);
|
||||||
for (var j = 0; j < rule.eventDescriptors.count; j++) {
|
for (var j = 0; j < rule.eventDescriptors.count; j++) {
|
||||||
var eventDescriptor = rule.eventDescriptors.get(j);
|
var eventDescriptor = rule.eventDescriptors.get(j);
|
||||||
if (eventDescriptor.eventTypeId === root.deviceClass.eventTypes.findByName("triggered").id) {
|
if (eventDescriptor.eventTypeId === root.logsModel.typeId) {
|
||||||
var matching = true;
|
var matching = true;
|
||||||
for (var k = 0; k < eventDescriptor.paramDescriptors.count; k++) {
|
for (var k = 0; k < eventDescriptor.paramDescriptors.count; k++) {
|
||||||
var paramDescriptor = eventDescriptor.paramDescriptors.get(k);
|
var paramDescriptor = eventDescriptor.paramDescriptors.get(k);
|
||||||
@ -105,6 +96,12 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: root.logsModel.busy
|
||||||
|
running: visible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,13 @@ GenericDevicePage {
|
|||||||
GenericTypeLogView {
|
GenericTypeLogView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
text: qsTr("This button has been pressed %1 times in the last 24 hours.")
|
text: qsTr("This button has been pressed %1 times in the last 24 hours.")
|
||||||
device: root.device
|
|
||||||
typeId: root.deviceClass.eventTypes.findByName("pressed").id
|
logsModel: LogsModel {
|
||||||
|
deviceId: root.device.id
|
||||||
|
live: true
|
||||||
|
typeId: root.deviceClass.eventTypes.findByName("pressed").id
|
||||||
|
Component.onCompleted: update()
|
||||||
|
}
|
||||||
|
|
||||||
onAddRuleClicked: {
|
onAddRuleClicked: {
|
||||||
var rule = Engine.ruleManager.createNewRule();
|
var rule = Engine.ruleManager.createNewRule();
|
||||||
|
|||||||
@ -36,6 +36,7 @@ Page {
|
|||||||
id: stateLabel
|
id: stateLabel
|
||||||
Layout.preferredWidth: parent.width / 2
|
Layout.preferredWidth: parent.width / 2
|
||||||
text: displayName
|
text: displayName
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
@ -73,6 +74,7 @@ Page {
|
|||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
anchors.margins: -app.margins / 2
|
||||||
onClicked: pageStack.push(Qt.resolvedUrl("StateLogPage.qml"),
|
onClicked: pageStack.push(Qt.resolvedUrl("StateLogPage.qml"),
|
||||||
{device: root.device, stateType: stateType})
|
{device: root.device, stateType: stateType})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,12 @@ GenericDevicePage {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
text: qsTr("This event has appeared %1 times in the last 24 hours.")
|
text: qsTr("This event has appeared %1 times in the last 24 hours.")
|
||||||
|
|
||||||
device: root.device
|
logsModel: LogsModel {
|
||||||
|
deviceId: root.device.id
|
||||||
|
live: true
|
||||||
|
Component.onCompleted: update()
|
||||||
|
typeId: root.deviceClass.eventTypes.findByName("triggered").id;
|
||||||
|
}
|
||||||
|
|
||||||
onAddRuleClicked: {
|
onAddRuleClicked: {
|
||||||
var rule = Engine.ruleManager.createNewRule();
|
var rule = Engine.ruleManager.createNewRule();
|
||||||
|
|||||||
@ -11,30 +11,159 @@ Page {
|
|||||||
property var device: null
|
property var device: null
|
||||||
property var stateType: null
|
property var stateType: null
|
||||||
|
|
||||||
|
readonly property bool canShowGraph: {
|
||||||
|
switch (root.stateType.type) {
|
||||||
|
case "Int":
|
||||||
|
case "Double":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
print("not showing graph for", root.stateType.type)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
header: GuhHeader {
|
header: GuhHeader {
|
||||||
text: qsTr("History")
|
text: qsTr("History")
|
||||||
onBackPressed: pageStack.pop()
|
onBackPressed: pageStack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericTypeLogView {
|
LogsModel {
|
||||||
anchors.fill: parent
|
id: logsModel
|
||||||
device: root.device
|
deviceId: root.device.id
|
||||||
|
live: true
|
||||||
|
Component.onCompleted: update()
|
||||||
typeId: root.stateType.id
|
typeId: root.stateType.id
|
||||||
text: qsTr("%1, %2 has changed %3 times in the last 24h").arg(device.name).arg(stateType.displayName)
|
}
|
||||||
|
|
||||||
onAddRuleClicked: {
|
// LogsModelNg {
|
||||||
var rule = Engine.ruleManager.createNewRule();
|
// id: logsModelNg
|
||||||
rule.createStateEvaluator();
|
// deviceId: root.device.id
|
||||||
rule.stateEvaluator.stateDescriptor.deviceId = device.id;
|
// typeId: root.stateType.id
|
||||||
rule.stateEvaluator.stateDescriptor.stateTypeId = root.stateType.id;
|
// startTime: {
|
||||||
rule.stateEvaluator.stateDescriptor.value = value;
|
// var date = new Date();
|
||||||
rule.stateEvaluator.stateDescriptor.valueOperator = StateDescriptor.ValueOperatorEquals;
|
// date.setHours(new Date().getHours() - 24)
|
||||||
rule.name = root.device.name + " - " + stateType.displayName + " = " + value;
|
// return date;
|
||||||
|
// }
|
||||||
|
// endTime: new Date();
|
||||||
|
// }
|
||||||
|
|
||||||
var rulePage = pageStack.push(Qt.resolvedUrl("../magic/DeviceRulesPage.qml"), {device: root.device});
|
ColumnLayout {
|
||||||
rulePage.addRule(rule);
|
anchors.fill: parent
|
||||||
|
|
||||||
|
TabBar {
|
||||||
|
id: tabBar
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.canShowGraph
|
||||||
|
TabButton {
|
||||||
|
text: qsTr("Log")
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: qsTr("Graph")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwipeView {
|
||||||
|
id: swipeView
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
currentIndex: tabBar.currentIndex
|
||||||
|
interactive: false
|
||||||
|
|
||||||
|
GenericTypeLogView {
|
||||||
|
id: logView
|
||||||
|
width: swipeView.width
|
||||||
|
height: swipeView.height
|
||||||
|
text: qsTr("%1, %2 has changed %3 times in the last 24h").arg(device.name).arg(stateType.displayName)
|
||||||
|
|
||||||
|
logsModel: logsModel
|
||||||
|
|
||||||
|
onAddRuleClicked: {
|
||||||
|
var rule = Engine.ruleManager.createNewRule();
|
||||||
|
rule.createStateEvaluator();
|
||||||
|
rule.stateEvaluator.stateDescriptor.deviceId = device.id;
|
||||||
|
rule.stateEvaluator.stateDescriptor.stateTypeId = root.stateType.id;
|
||||||
|
rule.stateEvaluator.stateDescriptor.value = value;
|
||||||
|
rule.stateEvaluator.stateDescriptor.valueOperator = StateDescriptor.ValueOperatorEquals;
|
||||||
|
rule.name = root.device.name + " - " + stateType.displayName + " = " + value;
|
||||||
|
|
||||||
|
var rulePage = pageStack.push(Qt.resolvedUrl("../magic/DeviceRulesPage.qml"), {device: root.device});
|
||||||
|
rulePage.addRule(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
width: swipeView.width
|
||||||
|
height: swipeView.height
|
||||||
|
TabBar {
|
||||||
|
id: zoomTabBar
|
||||||
|
Layout.fillWidth: true
|
||||||
|
TabButton {
|
||||||
|
text: qsTr("6 h")
|
||||||
|
property int avg: ValueLogsProxyModel.AverageQuarterHour
|
||||||
|
property date startTime: {
|
||||||
|
var date = new Date();
|
||||||
|
date.setHours(new Date().getHours() - 6)
|
||||||
|
date.setMinutes(0)
|
||||||
|
date.setSeconds(0)
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: qsTr("24 h")
|
||||||
|
property int avg: ValueLogsProxyModel.AverageHourly
|
||||||
|
property date startTime: {
|
||||||
|
var date = new Date();
|
||||||
|
date.setHours(new Date().getHours() - 24);
|
||||||
|
date.setMinutes(0)
|
||||||
|
date.setSeconds(0)
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: qsTr("7 d")
|
||||||
|
property int avg: ValueLogsProxyModel.AverageDayTime
|
||||||
|
property date startTime: {
|
||||||
|
var date = new Date();
|
||||||
|
date.setDate(new Date().getDate() - 7);
|
||||||
|
date.setHours(0)
|
||||||
|
date.setMinutes(0)
|
||||||
|
date.setSeconds(0)
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
mode: settings.graphStyle
|
||||||
|
color: app.guhAccent
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: updateTimer
|
||||||
|
interval: 10
|
||||||
|
repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
graphModel.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model: ValueLogsProxyModel {
|
||||||
|
id: graphModel
|
||||||
|
deviceId: root.device.id
|
||||||
|
typeId: stateType.id
|
||||||
|
average: zoomTabBar.currentItem.avg
|
||||||
|
startTime: zoomTabBar.currentItem.startTime
|
||||||
|
Component.onCompleted: updateTimer.start();
|
||||||
|
onAverageChanged: updateTimer.start()
|
||||||
|
onStartTimeChanged: updateTimer.start();
|
||||||
|
|
||||||
|
// Live doesn't work yet with ValueLogsProxyModel
|
||||||
|
// live: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user