This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
2021-04-12 11:08:15 +02:00

317 lines
11 KiB
QML

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import QtQuick.Layouts 1.1
import Nymea 1.0
import "../components"
import "../customviews"
Page {
id: root
property Thing thing: null
property alias device: root.thing
property var filterTypeIds: []
header: NymeaHeader {
text: qsTr("History for %1").arg(root.thing.name)
onBackPressed: pageStack.pop()
HeaderButton {
imageSource: "../images/filters.svg"
color: logsModelNg.filterEnabled ? Style.accentColor : Style.iconColor
onClicked: logsModelNg.filterEnabled = !logsModelNg.filterEnabled
visible: root.filterTypeIds.length === 0
}
}
LogsModelNg {
id: logsModelNg
engine: _engine
thingId: root.thing.id
typeIds: root.filterTypeIds.length > 0
? root.filterTypeIds
: filterEnabled
? [filterDeviceModel.getData(filterComboBox.currentIndex, ThingModel.RoleId)]
: []
live: true
property bool filterEnabled: false
}
ThingModel {
id: filterDeviceModel
thing: root.thing
}
Pane {
id: filterPane
anchors { left: parent.left; top: parent.top; right: parent.right }
Behavior on height { NumberAnimation { duration: 120; easing.type: Easing.InOutQuad } }
height: logsModelNg.filterEnabled ? implicitHeight + app.margins * 2 : 0
Material.elevation: 1
leftPadding: 0; rightPadding: 0; topPadding: 0; bottomPadding: 0
contentItem: Item {
clip: true
RowLayout {
anchors.fill: parent
anchors.margins: app.margins
spacing: app.margins
Label {
text: qsTr("Filter by")
}
ComboBox {
id: filterComboBox
Layout.fillWidth: true
textRole: "displayName"
model: filterDeviceModel
}
}
}
}
Loader {
id: graphLoader
anchors {
left: parent.left
top: filterPane.bottom
right: parent.right
}
readonly property StateType stateType: root.thing.thingClass.stateTypes.getStateType(root.filterTypeIds[0])
readonly property bool canShowGraph: {
if (stateType === null) {
return false
}
if (stateType.unit === Types.UnitUnixTime) {
return false;
}
switch (stateType.type.toLowerCase()) {
case "uint":
case "int":
case "double":
case "bool":
return true;
}
print("not showing graph for", stateType.type)
return false;
}
Component.onCompleted: {
if (root.filterTypeIds.length === 0) {
return;
}
if (!canShowGraph) {
return;
}
var source = Qt.resolvedUrl("../customviews/GenericTypeGraph.qml");
setSource(source, {thing: root.thing, stateType: stateType})
}
}
ListView {
anchors { left: parent.left; top: graphLoader.bottom; right: parent.right; bottom: parent.bottom }
clip: true
model: logsModelNg
ScrollBar.vertical: ScrollBar {}
BusyIndicator {
anchors.centerIn: parent
visible: logsModelNg.busy
}
delegate: ItemDelegate {
id: entryDelegate
width: parent.width
property StateType stateType: model.source === LogEntry.LoggingSourceStates ? root.thing.thingClass.stateTypes.getStateType(model.typeId) : null
property EventType eventType: model.source === LogEntry.LoggingSourceEvents || model.source === LogEntry.LoggingSourceStates ? root.thing.thingClass.eventTypes.getEventType(model.typeId) : null
property ActionType actionType: model.source === LogEntry.LoggingSourceActions ? root.thing.thingClass.actionTypes.getActionType(model.typeId) : null
contentItem: RowLayout {
ColorIcon {
Layout.preferredWidth: Style.iconSize
Layout.preferredHeight: width
Layout.alignment: Qt.AlignVCenter
color: {
switch (model.source) {
case LogEntry.LoggingSourceStates:
case LogEntry.LoggingSourceSystem:
case LogEntry.LoggingSourceActions:
case LogEntry.LoggingSourceEvents:
return Style.accentColor
case LogEntry.LoggingSourceRules:
if (model.loggingEventType === LogEntry.LoggingEventTypeActiveChange) {
return model.value === true ? "green" : Style.iconColor
}
return Style.accentColor
}
}
name: {
switch (model.source) {
case LogEntry.LoggingSourceStates:
return "../images/state.svg"
case LogEntry.LoggingSourceSystem:
return "../images/system-shutdown.svg"
case LogEntry.LoggingSourceActions:
return "../images/action.svg"
case LogEntry.LoggingSourceEvents:
return "../images/event.svg"
case LogEntry.LoggingSourceRules:
return "../images/magic.svg"
}
}
}
ColumnLayout {
RowLayout {
Label {
text: {
switch (model.source) {
case LogEntry.LoggingSourceStates:
// return entryDelegate.stateType.displayName
case LogEntry.LoggingSourceEvents:
return entryDelegate.eventType.displayName
case LogEntry.LoggingSourceActions:
return entryDelegate.actionType.displayName
}
}
Layout.fillWidth: true
elide: Text.ElideRight
}
Label {
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy hh:mm:ss")
elide: Text.ElideRight
font.pixelSize: app.smallFont
enabled: false
}
}
RowLayout {
Loader {
id: valueLoader
Layout.fillWidth: true
sourceComponent: {
switch (model.source) {
case LogEntry.LoggingSourceStates:
switch (entryDelegate.stateType.type.toLowerCase()) {
case "bool":
return boolComponent;
case "color":
return colorComponent
default:
if (entryDelegate.stateType.unit == Types.UnitUnixTime) {
return dateTimeComponent
}
return labelComponent
}
case LogEntry.LoggingSourceActions:
break;
case LogEntry.LoggingSourceEvents:
break;
}
return labelComponent
}
Binding { target: valueLoader.item; property: "value"; value: entryDelegate.stateType ? Types.toUiValue(model.value, entryDelegate.stateType.unit) : model.value }
Binding {
target: entryDelegate.stateType && valueLoader.item.hasOwnProperty("unitString") ? valueLoader.item : null;
property: "unitString"
value: entryDelegate.stateType ? Types.toUiUnit(entryDelegate.stateType.unit) : ""
}
}
}
}
}
}
}
Component {
id: labelComponent
Label {
property var value
property string unitString
text: value + " " + unitString
font.pixelSize: app.smallFont
elide: Text.ElideRight
}
}
Component {
id: dateTimeComponent
Label {
property var value
text: Qt.formatDateTime(new Date(value * 1000), Qt.DefaultLocaleShortDate)
}
}
Component {
id: boolComponent
Item {
id: boolLed
property var value
Led {
implicitHeight: app.smallFont
state: boolLed.value === "true" ? "on" : "off"
}
}
}
Component {
id: colorComponent
Item {
property var value
implicitHeight: app.smallFont
Rectangle {
height: parent.height
width: height * 2
color: parent.value
// radius: width / 2
border.color: Style.foregroundColor
border.width: 1
}
}
}
}