More polishing
This commit is contained in:
parent
d0fed74a24
commit
0e5619b4f9
@ -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)
|
||||
|
||||
@ -119,7 +119,8 @@ Item {
|
||||
"phsensor",
|
||||
"pressuresensor",
|
||||
"waterlevelsensor",
|
||||
"windspeedsensor"
|
||||
"windspeedsensor",
|
||||
"noisesensor"
|
||||
]
|
||||
if (progressInterfaces.indexOf(root.interfaceName) >= 0) {
|
||||
return progressComponent
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user