More polishing

This commit is contained in:
Michael Zanetti 2023-04-26 23:44:41 +02:00
parent d0fed74a24
commit 0e5619b4f9
5 changed files with 149 additions and 61 deletions

View File

@ -355,12 +355,18 @@ void NewLogsModel::fetchLogs()
qCDebug(dcLogEngine()) << "Fetching logs:" << QJsonDocument::fromVariant(params).toJson();
m_engine->jsonRpcClient()->sendCommand("Logging.GetLogEntries", params, this, "logsReply");
m_busy = true;
emit busyChanged();
}
void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
{
Q_UNUSED(commandId)
m_busy = false;
emit busyChanged();
QList<NewLogEntry*> entries;
foreach (const QVariant &entryVariant, data.value("logEntries").toList()) {
QVariantMap map = entryVariant.toMap();
@ -375,10 +381,6 @@ void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
m_canFetchMore = entries.count() >= m_blockSize;
qCDebug(dcLogEngine()) << "Logs received:" << entries.count();
if (entries.empty()) {
return;
}
if (!m_startTime.isNull() && !m_endTime.isNull()) {
beginResetModel();
QList<NewLogEntry*> oldEntries = m_list;
@ -387,22 +389,27 @@ void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
emit entriesRemoved(0, oldEntries.count());
qDeleteAll(oldEntries);
beginInsertRows(QModelIndex(), 0, entries.count() - 1);
m_list = entries;
endInsertRows();
emit entriesAdded(0, entries);
if (!entries.isEmpty()) {
beginInsertRows(QModelIndex(), 0, entries.count() - 1);
m_list = entries;
endInsertRows();
emit entriesAdded(0, entries);
}
emit countChanged();
} else {
beginInsertRows(QModelIndex(), m_list.count(), m_list.count() + entries.count() - 1);
qSort(entries.begin(), entries.end(), [](NewLogEntry *left, NewLogEntry *right){
return left->timestamp() > right->timestamp();
});
m_list.append(entries);
endInsertRows();
emit entriesAdded(m_list.count() - entries.count(), entries);
if (!entries.isEmpty()) {
beginInsertRows(QModelIndex(), m_list.count(), m_list.count() + entries.count() - 1);
qSort(entries.begin(), entries.end(), [](NewLogEntry *left, NewLogEntry *right){
return left->timestamp() > right->timestamp();
});
m_list.append(entries);
endInsertRows();
emit entriesAdded(m_list.count() - entries.count(), entries);
emit countChanged();
}
}
emit countChanged();
}
void NewLogsModel::newLogEntryReceived(const QVariantMap &map)

View File

@ -119,7 +119,8 @@ Item {
"phsensor",
"pressuresensor",
"waterlevelsensor",
"windspeedsensor"
"windspeedsensor",
"noisesensor"
]
if (progressInterfaces.indexOf(root.interfaceName) >= 0) {
return progressComponent

View File

@ -53,12 +53,19 @@ Item {
NewLogsModel {
id: logsModel
engine: root.thing && root.stateType ? _engine : null
engine: _engine
source: root.thing ? "state-" + thing.id + "-" + root.stateType.name : ""
startTime: new Date(d.startTime.getTime() - d.range * 1.1 * 60000)
endTime: new Date(d.endTime.getTime() + d.range * 1.1 * 60000)
sampleRate: d.sampleRate
Component.onCompleted: {
if (source != "") {
fetchLogs()
}
}
onSourceChanged: fetchLogs()
property double minValue
property double maxValue
@ -127,10 +134,6 @@ Item {
zeroSeries.shrink()
}
onEngineChanged: fetchLogs()
Component.onCompleted: fetchLogs()
}
ColumnLayout {
@ -183,6 +186,7 @@ Item {
onTabSelected: {
d.now = new Date()
logsModel.clear()
print("*** tab selected")
logsModel.fetchLogs()
}
}
@ -191,6 +195,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
ChartView {
id: chartView
anchors.fill: parent
@ -208,6 +213,41 @@ Item {
legend.font: Style.extraSmallFont
legend.visible: false
ActivityIndicator {
anchors.centerIn: parent
visible: logsModel.busy
opacity: .5
}
Label {
anchors.centerIn: parent
visible: !logsModel.busy && logsModel.count == 0
text: qsTr("No data")
font: Style.smallFont
opacity: .5
}
Label {
x: chartView.x + chartView.plotArea.x + (chartView.plotArea.width - width) / 2
y: chartView.y + chartView.plotArea.y + Style.smallMargins
text: {
switch (d.sampleRate) {
case NewLogsModel.SampleRate1Min:
return d.startTime.toLocaleDateString(Qt.locale(), Locale.LongFormat)
case NewLogsModel.SampleRate15Mins:
case NewLogsModel.SampleRate1Hour:
case NewLogsModel.SampleRate3Hours:
case NewLogsModel.SampleRate1Day:
case NewLogsModel.SampleRate1Week:
case NewLogsModel.SampleRate1Month:
case NewLogsModel.SampleRate1Year:
return d.startTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat) + " - " + d.endTime.toLocaleDateString(Qt.locale(), Locale.ShortFormat)
}
}
font: Style.smallFont
opacity: ((new Date().getTime() - d.now.getTime()) / d.sampleRate / 60000) > d.visibleValues ? .5 : 0
Behavior on opacity { NumberAnimation {} }
}
ValueAxis {
id: valueAxis
min: logsModel.minValue == undefined || logsModel.minValue == 0
@ -217,28 +257,31 @@ Item {
? 0
: logsModel.maxValue + 5
labelFormat: ""
labelFormat: "%0.0f " + Types.toUiUnit(root.stateType.unit)
gridLineColor: Style.tileOverlayColor
labelsVisible: false
lineVisible: false
titleVisible: false
shadesVisible: false
labelsFont: Style.extraSmallFont
labelsColor: Style.foregroundColor
}
// Overriding the labels with our own as printf struggles with special chars
Item {
id: labelsLayout
x: Style.smallMargins
y: chartView.plotArea.y
height: chartView.plotArea.height
width: chartView.plotArea.x - x
visible: root.stateType.type.toLowerCase() != "bool"
visible: root.stateType.type.toLowerCase() != "bool" && logsModel.minValue != logsModel.maxValue
Repeater {
model: valueAxis.tickCount
delegate: Label {
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
width: parent.width - Style.smallMargins
horizontalAlignment: Text.AlignRight
text: root.stateType ? Types.toUiValue(((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1)))), root.stateType.unit).toFixed(0) + Types.toUiUnit(root.stateType.unit) : ""
text: root.stateType ? Types.toUiValue(((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1)))), root.stateType.unit).toFixed(0) + " " + Types.toUiUnit(root.stateType.unit) : ""
verticalAlignment: Text.AlignTop
font: Style.extraSmallFont
}
@ -457,12 +500,12 @@ Item {
width: 1
color: Style.foregroundColor
x: Math.min(mouseArea.width, Math.max(0, toolTip.entryX))
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging
visible: toolTip.visible
}
NymeaToolTip {
id: toolTip
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging && logsModel.count > 0
backgroundItem: chartView
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)

View File

@ -42,35 +42,46 @@ BigThingTile {
id: dataGrid
columns: Math.floor(contentItem.width / 120)
ListModel {
id: interfacesModel
ListElement { interfaceName: "temperaturesensor"; stateName: "temperature" }
ListElement { interfaceName: "humiditysensor"; stateName: "humidity" }
ListElement { interfaceName: "moisturesensor"; stateName: "moisture" }
ListElement { interfaceName: "pressuresensor"; stateName: "pressure" }
ListElement { interfaceName: "lightsensor"; stateName: "lightIntensity" }
ListElement { interfaceName: "conductivitysensor"; stateName: "conductivity" }
ListElement { interfaceName: "noisesensor"; stateName: "noise" }
ListElement { interfaceName: "cosensor"; stateName: "co" }
ListElement { interfaceName: "co2sensor"; stateName: "co2" }
ListElement { interfaceName: "gassensor"; stateName: "gasLevel" }
ListElement { interfaceName: "daylightsensor"; stateName: "daylight" }
ListElement { interfaceName: "presencesensor"; stateName: "isPresent" }
ListElement { interfaceName: "vibrationsensor"; stateName: ""; eventName: "vibrationDetected" }
ListElement { interfaceName: "closablesensor"; stateName: "closed" }
ListElement { interfaceName: "heating"; stateName: "power" }
ListElement { interfaceName: "thermostat"; stateName: "targetTemperature" }
ListElement { interfaceName: "watersensor"; stateName: "waterDetected" }
ListElement { interfaceName: "waterlevelsensor"; stateName: "waterLevel" }
ListElement { interfaceName: "firesensor"; stateName: "fireDetected" }
ListElement { interfaceName: "o2sensor"; stateName: "o2saturation" }
ListElement { interfaceName: "phsensor"; stateName: "ph" }
ListElement { interfaceName: "orpsensor"; stateName: "orp" }
ListElement { interfaceName: "vocsensor"; stateName: "voc" }
ListElement { interfaceName: "pm10sensor"; stateName: "pm10" }
ListElement { interfaceName: "pm25sensor"; stateName: "pm25" }
ListElement { interfaceName: "no2sensor"; stateName: "no2" }
ListElement { interfaceName: "o3sensor"; stateName: "o3" }
}
Repeater {
model: ListModel {
ListElement { interfaceName: "temperaturesensor"; stateName: "temperature" }
ListElement { interfaceName: "humiditysensor"; stateName: "humidity" }
ListElement { interfaceName: "moisturesensor"; stateName: "moisture" }
ListElement { interfaceName: "pressuresensor"; stateName: "pressure" }
ListElement { interfaceName: "lightsensor"; stateName: "lightIntensity" }
ListElement { interfaceName: "conductivitysensor"; stateName: "conductivity" }
ListElement { interfaceName: "noisesensor"; stateName: "noise" }
ListElement { interfaceName: "cosensor"; stateName: "co" }
ListElement { interfaceName: "co2sensor"; stateName: "co2" }
ListElement { interfaceName: "gassensor"; stateName: "gasLevel" }
ListElement { interfaceName: "daylightsensor"; stateName: "daylight" }
ListElement { interfaceName: "presencesensor"; stateName: "isPresent" }
ListElement { interfaceName: "vibrationsensor"; stateName: ""; eventName: "vibrationDetected" }
ListElement { interfaceName: "closablesensor"; stateName: "closed" }
ListElement { interfaceName: "heating"; stateName: "power" }
ListElement { interfaceName: "thermostat"; stateName: "targetTemperature" }
ListElement { interfaceName: "watersensor"; stateName: "waterDetected" }
ListElement { interfaceName: "waterlevelsensor"; stateName: "waterLevel" }
ListElement { interfaceName: "firesensor"; stateName: "fireDetected" }
ListElement { interfaceName: "o2sensor"; stateName: "o2saturation" }
ListElement { interfaceName: "phsensor"; stateName: "ph" }
ListElement { interfaceName: "orpsensor"; stateName: "orp" }
ListElement { interfaceName: "vocsensor"; stateName: "voc" }
ListElement { interfaceName: "pm10sensor"; stateName: "pm10" }
ListElement { interfaceName: "pm25sensor"; stateName: "pm25" }
ListElement { interfaceName: "no2sensor"; stateName: "no2" }
ListElement { interfaceName: "o3sensor"; stateName: "o3" }
dynamicRoles: true
Component.onCompleted: {
for (var i = 0; i < interfacesModel.count; i++) {
if (itemDelegate.thing.thingClass.interfaces.indexOf(interfacesModel.get(i).interfaceName) >= 0) {
append(interfacesModel.get(i))
}
}
}
}
delegate: RowLayout {
@ -82,15 +93,40 @@ BigThingTile {
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
property EventType eventType: itemDelegate.thing.thingClass.eventTypes.findByName(model.eventName)
LogsModel {
id: eventLogsModel
engine: sensorValueDelegate.eventType != null ? _engine : null
thingId: itemDelegate.thing.id
typeIds: sensorValueDelegate.eventType != null ? [sensorValueDelegate.eventType.id] : []
live: true
fetchBlockSize: 1
property QtObject eventLogsModel: {
if (model.eventName) {
if (engine.jsonRpcClient.ensureServerVersion("8.0")) {
return eventLogsModelComponent.createObject(sensorValueDelegate)
}
return legacyEventLogsModelComponent.createObject(sensorValueDelegate)
}
return null
}
Component {
id: legacyEventLogsModelComponent
LogsModel {
objectName: itemDelegate.thing.name + "-" + model.eventName
engine: sensorValueDelegate.eventType != null ? _engine : null
thingId: itemDelegate.thing.id
typeIds: sensorValueDelegate.eventType != null ? [sensorValueDelegate.eventType.id] : []
live: true
fetchBlockSize: 1
}
}
Component {
id: eventLogsModelComponent
NewLogsModel {
engine: _engine
source: "event-" + itemDelegate.thing.id + "-" + model.eventName
live: true
fetchBlockSize: 1
Component.onCompleted: fetchLogs()
}
}
ColorIcon {
Layout.preferredHeight: Style.iconSize
Layout.preferredWidth: height

View File

@ -73,6 +73,7 @@ Page {
NymeaDialog {
title: qsTr("Remove logs?")
text: qsTr("Do you want to remove the log for this state and disable logging?")
standardButtons: Dialog.Yes | Dialog.No
onAccepted: engine.thingManager.setStateLogging(root.thing.id, root.stateType.id, false)
}
}