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();
|
qCDebug(dcLogEngine()) << "Fetching logs:" << QJsonDocument::fromVariant(params).toJson();
|
||||||
m_engine->jsonRpcClient()->sendCommand("Logging.GetLogEntries", params, this, "logsReply");
|
m_engine->jsonRpcClient()->sendCommand("Logging.GetLogEntries", params, this, "logsReply");
|
||||||
|
|
||||||
|
m_busy = true;
|
||||||
|
emit busyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
|
void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
|
||||||
{
|
{
|
||||||
Q_UNUSED(commandId)
|
Q_UNUSED(commandId)
|
||||||
|
|
||||||
|
m_busy = false;
|
||||||
|
emit busyChanged();
|
||||||
|
|
||||||
QList<NewLogEntry*> entries;
|
QList<NewLogEntry*> entries;
|
||||||
foreach (const QVariant &entryVariant, data.value("logEntries").toList()) {
|
foreach (const QVariant &entryVariant, data.value("logEntries").toList()) {
|
||||||
QVariantMap map = entryVariant.toMap();
|
QVariantMap map = entryVariant.toMap();
|
||||||
@ -375,10 +381,6 @@ void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
|
|||||||
m_canFetchMore = entries.count() >= m_blockSize;
|
m_canFetchMore = entries.count() >= m_blockSize;
|
||||||
qCDebug(dcLogEngine()) << "Logs received:" << entries.count();
|
qCDebug(dcLogEngine()) << "Logs received:" << entries.count();
|
||||||
|
|
||||||
if (entries.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_startTime.isNull() && !m_endTime.isNull()) {
|
if (!m_startTime.isNull() && !m_endTime.isNull()) {
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
QList<NewLogEntry*> oldEntries = m_list;
|
QList<NewLogEntry*> oldEntries = m_list;
|
||||||
@ -387,22 +389,27 @@ void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
|
|||||||
emit entriesRemoved(0, oldEntries.count());
|
emit entriesRemoved(0, oldEntries.count());
|
||||||
qDeleteAll(oldEntries);
|
qDeleteAll(oldEntries);
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(), 0, entries.count() - 1);
|
if (!entries.isEmpty()) {
|
||||||
m_list = entries;
|
beginInsertRows(QModelIndex(), 0, entries.count() - 1);
|
||||||
endInsertRows();
|
m_list = entries;
|
||||||
emit entriesAdded(0, entries);
|
endInsertRows();
|
||||||
|
emit entriesAdded(0, entries);
|
||||||
|
}
|
||||||
|
emit countChanged();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count() + entries.count() - 1);
|
if (!entries.isEmpty()) {
|
||||||
qSort(entries.begin(), entries.end(), [](NewLogEntry *left, NewLogEntry *right){
|
beginInsertRows(QModelIndex(), m_list.count(), m_list.count() + entries.count() - 1);
|
||||||
return left->timestamp() > right->timestamp();
|
qSort(entries.begin(), entries.end(), [](NewLogEntry *left, NewLogEntry *right){
|
||||||
});
|
return left->timestamp() > right->timestamp();
|
||||||
m_list.append(entries);
|
});
|
||||||
endInsertRows();
|
m_list.append(entries);
|
||||||
emit entriesAdded(m_list.count() - entries.count(), entries);
|
endInsertRows();
|
||||||
|
emit entriesAdded(m_list.count() - entries.count(), entries);
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit countChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewLogsModel::newLogEntryReceived(const QVariantMap &map)
|
void NewLogsModel::newLogEntryReceived(const QVariantMap &map)
|
||||||
|
|||||||
@ -119,7 +119,8 @@ Item {
|
|||||||
"phsensor",
|
"phsensor",
|
||||||
"pressuresensor",
|
"pressuresensor",
|
||||||
"waterlevelsensor",
|
"waterlevelsensor",
|
||||||
"windspeedsensor"
|
"windspeedsensor",
|
||||||
|
"noisesensor"
|
||||||
]
|
]
|
||||||
if (progressInterfaces.indexOf(root.interfaceName) >= 0) {
|
if (progressInterfaces.indexOf(root.interfaceName) >= 0) {
|
||||||
return progressComponent
|
return progressComponent
|
||||||
|
|||||||
@ -53,12 +53,19 @@ Item {
|
|||||||
|
|
||||||
NewLogsModel {
|
NewLogsModel {
|
||||||
id: logsModel
|
id: logsModel
|
||||||
engine: root.thing && root.stateType ? _engine : null
|
engine: _engine
|
||||||
source: root.thing ? "state-" + thing.id + "-" + root.stateType.name : ""
|
source: root.thing ? "state-" + thing.id + "-" + root.stateType.name : ""
|
||||||
startTime: new Date(d.startTime.getTime() - d.range * 1.1 * 60000)
|
startTime: new Date(d.startTime.getTime() - d.range * 1.1 * 60000)
|
||||||
endTime: new Date(d.endTime.getTime() + d.range * 1.1 * 60000)
|
endTime: new Date(d.endTime.getTime() + d.range * 1.1 * 60000)
|
||||||
sampleRate: d.sampleRate
|
sampleRate: d.sampleRate
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (source != "") {
|
||||||
|
fetchLogs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSourceChanged: fetchLogs()
|
||||||
|
|
||||||
property double minValue
|
property double minValue
|
||||||
property double maxValue
|
property double maxValue
|
||||||
|
|
||||||
@ -127,10 +134,6 @@ Item {
|
|||||||
|
|
||||||
zeroSeries.shrink()
|
zeroSeries.shrink()
|
||||||
}
|
}
|
||||||
|
|
||||||
onEngineChanged: fetchLogs()
|
|
||||||
Component.onCompleted: fetchLogs()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@ -183,6 +186,7 @@ Item {
|
|||||||
onTabSelected: {
|
onTabSelected: {
|
||||||
d.now = new Date()
|
d.now = new Date()
|
||||||
logsModel.clear()
|
logsModel.clear()
|
||||||
|
print("*** tab selected")
|
||||||
logsModel.fetchLogs()
|
logsModel.fetchLogs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,6 +195,7 @@ Item {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
|
||||||
ChartView {
|
ChartView {
|
||||||
id: chartView
|
id: chartView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -208,6 +213,41 @@ Item {
|
|||||||
legend.font: Style.extraSmallFont
|
legend.font: Style.extraSmallFont
|
||||||
legend.visible: false
|
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 {
|
ValueAxis {
|
||||||
id: valueAxis
|
id: valueAxis
|
||||||
min: logsModel.minValue == undefined || logsModel.minValue == 0
|
min: logsModel.minValue == undefined || logsModel.minValue == 0
|
||||||
@ -217,28 +257,31 @@ Item {
|
|||||||
? 0
|
? 0
|
||||||
: logsModel.maxValue + 5
|
: logsModel.maxValue + 5
|
||||||
|
|
||||||
labelFormat: ""
|
labelFormat: "%0.0f " + Types.toUiUnit(root.stateType.unit)
|
||||||
gridLineColor: Style.tileOverlayColor
|
gridLineColor: Style.tileOverlayColor
|
||||||
labelsVisible: false
|
labelsVisible: false
|
||||||
lineVisible: false
|
lineVisible: false
|
||||||
titleVisible: false
|
titleVisible: false
|
||||||
shadesVisible: false
|
shadesVisible: false
|
||||||
|
labelsFont: Style.extraSmallFont
|
||||||
|
labelsColor: Style.foregroundColor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// Overriding the labels with our own as printf struggles with special chars
|
||||||
Item {
|
Item {
|
||||||
id: labelsLayout
|
id: labelsLayout
|
||||||
x: Style.smallMargins
|
x: Style.smallMargins
|
||||||
y: chartView.plotArea.y
|
y: chartView.plotArea.y
|
||||||
height: chartView.plotArea.height
|
height: chartView.plotArea.height
|
||||||
width: chartView.plotArea.x - x
|
width: chartView.plotArea.x - x
|
||||||
visible: root.stateType.type.toLowerCase() != "bool"
|
visible: root.stateType.type.toLowerCase() != "bool" && logsModel.minValue != logsModel.maxValue
|
||||||
Repeater {
|
Repeater {
|
||||||
model: valueAxis.tickCount
|
model: valueAxis.tickCount
|
||||||
delegate: Label {
|
delegate: Label {
|
||||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||||
width: parent.width - Style.smallMargins
|
width: parent.width - Style.smallMargins
|
||||||
horizontalAlignment: Text.AlignRight
|
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
|
verticalAlignment: Text.AlignTop
|
||||||
font: Style.extraSmallFont
|
font: Style.extraSmallFont
|
||||||
}
|
}
|
||||||
@ -457,12 +500,12 @@ Item {
|
|||||||
width: 1
|
width: 1
|
||||||
color: Style.foregroundColor
|
color: Style.foregroundColor
|
||||||
x: Math.min(mouseArea.width, Math.max(0, toolTip.entryX))
|
x: Math.min(mouseArea.width, Math.max(0, toolTip.entryX))
|
||||||
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging
|
visible: toolTip.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
NymeaToolTip {
|
NymeaToolTip {
|
||||||
id: toolTip
|
id: toolTip
|
||||||
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging
|
visible: (mouseArea.containsMouse || mouseArea.tooltipping) && !mouseArea.dragging && logsModel.count > 0
|
||||||
|
|
||||||
backgroundItem: chartView
|
backgroundItem: chartView
|
||||||
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
|
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||||
|
|||||||
@ -42,35 +42,46 @@ BigThingTile {
|
|||||||
id: dataGrid
|
id: dataGrid
|
||||||
columns: Math.floor(contentItem.width / 120)
|
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 {
|
Repeater {
|
||||||
model: ListModel {
|
model: ListModel {
|
||||||
ListElement { interfaceName: "temperaturesensor"; stateName: "temperature" }
|
dynamicRoles: true
|
||||||
ListElement { interfaceName: "humiditysensor"; stateName: "humidity" }
|
Component.onCompleted: {
|
||||||
ListElement { interfaceName: "moisturesensor"; stateName: "moisture" }
|
for (var i = 0; i < interfacesModel.count; i++) {
|
||||||
ListElement { interfaceName: "pressuresensor"; stateName: "pressure" }
|
if (itemDelegate.thing.thingClass.interfaces.indexOf(interfacesModel.get(i).interfaceName) >= 0) {
|
||||||
ListElement { interfaceName: "lightsensor"; stateName: "lightIntensity" }
|
append(interfacesModel.get(i))
|
||||||
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" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
@ -82,15 +93,40 @@ BigThingTile {
|
|||||||
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
|
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
|
||||||
|
|
||||||
property EventType eventType: itemDelegate.thing.thingClass.eventTypes.findByName(model.eventName)
|
property EventType eventType: itemDelegate.thing.thingClass.eventTypes.findByName(model.eventName)
|
||||||
LogsModel {
|
|
||||||
id: eventLogsModel
|
property QtObject eventLogsModel: {
|
||||||
engine: sensorValueDelegate.eventType != null ? _engine : null
|
if (model.eventName) {
|
||||||
thingId: itemDelegate.thing.id
|
if (engine.jsonRpcClient.ensureServerVersion("8.0")) {
|
||||||
typeIds: sensorValueDelegate.eventType != null ? [sensorValueDelegate.eventType.id] : []
|
return eventLogsModelComponent.createObject(sensorValueDelegate)
|
||||||
live: true
|
}
|
||||||
fetchBlockSize: 1
|
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 {
|
ColorIcon {
|
||||||
Layout.preferredHeight: Style.iconSize
|
Layout.preferredHeight: Style.iconSize
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
|
|||||||
@ -73,6 +73,7 @@ Page {
|
|||||||
NymeaDialog {
|
NymeaDialog {
|
||||||
title: qsTr("Remove logs?")
|
title: qsTr("Remove logs?")
|
||||||
text: qsTr("Do you want to remove the log for this state and disable logging?")
|
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)
|
onAccepted: engine.thingManager.setStateLogging(root.thing.id, root.stateType.id, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user