Improve energy pages
This commit is contained in:
parent
a4336ae1c0
commit
dc399f28ae
@ -330,7 +330,7 @@ void LogsModel::fetchMore(const QModelIndex &parent)
|
|||||||
Q_UNUSED(parent)
|
Q_UNUSED(parent)
|
||||||
|
|
||||||
if (!m_engine) {
|
if (!m_engine) {
|
||||||
qCWarning(dcLogEngine()) << objectName() << "Cannot update. Engine not set";
|
qCDebug(dcLogEngine()) << objectName() << "Cannot update yet. Engine not set";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_busyInternal) {
|
if (m_busyInternal) {
|
||||||
|
|||||||
@ -257,5 +257,6 @@
|
|||||||
<file>ui/components/CircleBackground.qml</file>
|
<file>ui/components/CircleBackground.qml</file>
|
||||||
<file>ui/devicepages/CoolingThingPage.qml</file>
|
<file>ui/devicepages/CoolingThingPage.qml</file>
|
||||||
<file>ui/devicepages/EvChargerThingPage.qml</file>
|
<file>ui/devicepages/EvChargerThingPage.qml</file>
|
||||||
|
<file>ui/components/BlurredLabel.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -91,7 +91,8 @@ Item {
|
|||||||
"o2sensor": "lightblue",
|
"o2sensor": "lightblue",
|
||||||
"orpsensor": "yellow",
|
"orpsensor": "yellow",
|
||||||
"powersocket": "aquamarine",
|
"powersocket": "aquamarine",
|
||||||
"evcharger": "limegreen"
|
"evcharger": "limegreen",
|
||||||
|
"energystorage": "limegreen"
|
||||||
}
|
}
|
||||||
|
|
||||||
property var stateColors: {
|
property var stateColors: {
|
||||||
@ -111,4 +112,5 @@ Item {
|
|||||||
readonly property int fastAnimationDuration: 100
|
readonly property int fastAnimationDuration: 100
|
||||||
readonly property int animationDuration: 150
|
readonly property int animationDuration: 150
|
||||||
readonly property int slowAnimationDuration: 300
|
readonly property int slowAnimationDuration: 300
|
||||||
|
readonly property int sleepyAnimationDuration: 2000
|
||||||
}
|
}
|
||||||
|
|||||||
37
nymea-app/ui/components/BlurredLabel.qml
Normal file
37
nymea-app/ui/components/BlurredLabel.qml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
implicitWidth: label.implicitWidth + Style.margins * 2
|
||||||
|
implicitHeight: label.implicitHeight + Style.margins * 2
|
||||||
|
|
||||||
|
property alias text: label.text
|
||||||
|
property alias wrapMode: label.wrapMode
|
||||||
|
property alias horizontalAlignment: label.horizontalAlignment
|
||||||
|
property alias textFormat: label.textFormat
|
||||||
|
|
||||||
|
property bool blurred: false
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: label
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderEffectSource {
|
||||||
|
id: effectSource
|
||||||
|
anchors.fill: parent
|
||||||
|
sourceItem: label
|
||||||
|
hideSource: true
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
FastBlur {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: effectSource
|
||||||
|
radius: root.blurred ? 32 : 0
|
||||||
|
Behavior on radius { NumberAnimation { duration: Style.animationDuration } }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -56,6 +56,13 @@ Item {
|
|||||||
radius: width / 2
|
radius: width / 2
|
||||||
color: Style.tileBackgroundColor
|
color: Style.tileBackgroundColor
|
||||||
}
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: mask
|
||||||
|
anchors.fill: background
|
||||||
|
radius: height / 2
|
||||||
|
visible: false
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: background
|
anchors.fill: background
|
||||||
@ -85,7 +92,7 @@ Item {
|
|||||||
opacity: root.on ? 1 : 0
|
opacity: root.on ? 1 : 0
|
||||||
anchors.fill: gradient
|
anchors.fill: gradient
|
||||||
source: gradient
|
source: gradient
|
||||||
maskSource: background
|
maskSource: mask
|
||||||
Behavior on opacity { NumberAnimation { duration: Style.animationDuration } }
|
Behavior on opacity { NumberAnimation { duration: Style.animationDuration } }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import QtCharts 2.2
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
implicitHeight: width * .6
|
implicitHeight: width * .6
|
||||||
|
implicitWidth: 400
|
||||||
|
|
||||||
property Thing thing: null
|
property Thing thing: null
|
||||||
property StateType stateType: null
|
property StateType stateType: null
|
||||||
|
|||||||
@ -66,52 +66,71 @@ ThingsListPageBase {
|
|||||||
thing: root.thingsProxy.getThing(model.id)
|
thing: root.thingsProxy.getThing(model.id)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
enterPage(index)
|
enterPage(index, ["energystorage", "smartmeter"])
|
||||||
}
|
}
|
||||||
contentItem: GridLayout {
|
contentItem: RowLayout {
|
||||||
id: dataGrid
|
id: dataGrid
|
||||||
columns: Math.floor(contentItem.width / 120)
|
|
||||||
|
|
||||||
Repeater {
|
property State currentPowerState: itemDelegate.thing.stateByName("currentPower")
|
||||||
model: ListModel {
|
property bool isEnergyMeter: itemDelegate.thing.thingClass.interfaces.indexOf("energymeter") >= 0
|
||||||
Component.onCompleted: {
|
property bool isBattery: itemDelegate.thing.thingClass.interfaces.indexOf("energystorage") >= 0
|
||||||
if (itemDelegate.thing.thingClass.stateTypes.findByName("totalEnergyConsumed") !== null) {
|
property bool isEvCharger: itemDelegate.thing.thingClass.interfaces.indexOf("evcharger") >= 0
|
||||||
append( {stateName: "totalEnergyConsumed" })
|
property bool isProducer: itemDelegate.thing.thingClass.interfaces.indexOf("smartmeterproducer") >= 0
|
||||||
|
property bool isConsumer: itemDelegate.thing.thingClass.interfaces.indexOf("smartmeterconsumer") >= 0
|
||||||
|
property bool isProduction: currentPowerState.value < 0
|
||||||
|
property bool isConsumption: currentPowerState.value > 0
|
||||||
|
property double absValue: Math.abs(currentPowerState.value)
|
||||||
|
property double cleanVale: (absValue / (absValue > 1000 ? 1000 : 1)).toFixed(1)
|
||||||
|
property string unit: absValue > 1000 ? "kW" : "W"
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
name: app.stateIcon("currentPower")
|
||||||
|
color: app.stateColor("currentPower")
|
||||||
|
size: Style.iconSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: {
|
||||||
|
if (dataGrid.isEnergyMeter) {
|
||||||
|
if (dataGrid.isProduction) {
|
||||||
|
return qsTr("%1 %2 returning").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
|
} else {
|
||||||
|
return qsTr("%1 %2 obtaining").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
}
|
}
|
||||||
if (itemDelegate.thing.thingClass.stateTypes.findByName("totalEnergyProduced") !== null) {
|
|
||||||
append( {stateName: "totalEnergyProduced" })
|
} else if (dataGrid.isBattery || dataGrid.isEvCharger) {
|
||||||
|
if (dataGrid.isProduction) {
|
||||||
|
return qsTr("%1 %2 discharging").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
|
} else {
|
||||||
|
return qsTr("%1 %2 charging").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
}
|
}
|
||||||
if (itemDelegate.thing.thingClass.stateTypes.findByName("currentPower") !== null) {
|
|
||||||
append({stateName: "currentPower"});
|
} else if (dataGrid.isProducer && !dataGrid.isConsumer) {
|
||||||
|
if (dataGrid.isProduction) {
|
||||||
|
return qsTr("%1 %2 producing").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
|
} else {
|
||||||
|
return qsTr("%1 %2 idling").arg(Math.max(0, dataGrid.cleanVale)).arg(dataGrid.unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (dataGrid.isConsumer && !dataGrid.isProducer) {
|
||||||
|
if (dataGrid.isProduction) {
|
||||||
|
return qsTr("%1 %2 idling").arg(Math.max(0, dataGrid.cleanVale)).arg(dataGrid.unit)
|
||||||
|
} else {
|
||||||
|
return qsTr("%1 %2 consuming").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (dataGrid.isProduction) {
|
||||||
|
return qsTr("%1 %2 producing").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
|
} else {
|
||||||
|
return qsTr("%1 %2 consuming").arg(dataGrid.cleanVale).arg(dataGrid.unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elide: Text.ElideRight
|
||||||
delegate: RowLayout {
|
verticalAlignment: Text.AlignVCenter
|
||||||
id: sensorValueDelegate
|
font.pixelSize: app.smallFont
|
||||||
Layout.preferredWidth: contentItem.width / dataGrid.columns
|
|
||||||
|
|
||||||
property StateType stateType: itemDelegate.thing.thingClass.stateTypes.findByName(model.stateName)
|
|
||||||
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
|
|
||||||
|
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredHeight: Style.iconSize
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
color: app.stateColor(model.stateName)
|
|
||||||
name: app.stateIcon(model.stateName)
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: sensorValueDelegate.stateValue
|
|
||||||
? "%1 %2".arg((1.0 * Math.round(Types.toUiValue(sensorValueDelegate.stateValue.value, sensorValueDelegate.stateType.unit) * 100000) / 100000).toFixed(3)).arg(Types.toUiUnit(sensorValueDelegate.stateType.unit))
|
|
||||||
: ""
|
|
||||||
elide: Text.ElideRight
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
font.pixelSize: app.smallFont
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,9 +44,14 @@ Page {
|
|||||||
|
|
||||||
property ThingsProxy thingsProxy: thingsProxyInternal
|
property ThingsProxy thingsProxy: thingsProxyInternal
|
||||||
|
|
||||||
function enterPage(index) {
|
function enterPage(index, interfaces) {
|
||||||
|
if (interfaces === undefined) {
|
||||||
|
interfaces = root.shownInterfaces
|
||||||
|
}
|
||||||
|
|
||||||
var thing = thingsProxy.get(index);
|
var thing = thingsProxy.get(index);
|
||||||
var page = NymeaUtils.interfaceListToDevicePage(root.shownInterfaces);
|
print("matching interfaces", interfaces)
|
||||||
|
var page = NymeaUtils.interfaceListToDevicePage(interfaces);
|
||||||
pageStack.push(Qt.resolvedUrl("../devicepages/" + page), {thing: thingsProxy.get(index)})
|
pageStack.push(Qt.resolvedUrl("../devicepages/" + page), {thing: thingsProxy.get(index)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -236,6 +236,8 @@ Page {
|
|||||||
return boolComponent;
|
return boolComponent;
|
||||||
case "color":
|
case "color":
|
||||||
return colorComponent
|
return colorComponent
|
||||||
|
case "double":
|
||||||
|
return floatLabelComponent;
|
||||||
default:
|
default:
|
||||||
if (entryDelegate.stateType.unit == Types.UnitUnixTime) {
|
if (entryDelegate.stateType.unit == Types.UnitUnixTime) {
|
||||||
return dateTimeComponent
|
return dateTimeComponent
|
||||||
@ -278,6 +280,17 @@ Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: floatLabelComponent
|
||||||
|
Label {
|
||||||
|
property double value
|
||||||
|
property string unitString
|
||||||
|
text: value.toFixed(value > 1000 ? 0 : 2) + " " + unitString
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: dateTimeComponent
|
id: dateTimeComponent
|
||||||
Label {
|
Label {
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 2.1
|
import QtQuick.Controls 2.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
import "../customviews"
|
import "../customviews"
|
||||||
@ -38,75 +39,232 @@ import "../customviews"
|
|||||||
ThingPageBase {
|
ThingPageBase {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property State totalEnergyConsumedState: root.thing.stateByName("totalEnergyConsumed")
|
readonly property bool isEnergyMeter: root.thing && root.thing.thingClass.interfaces.indexOf("energymeter") >= 0
|
||||||
readonly property StateType totalEnergyConsumedStateType: root.thing.thingClass.stateTypes.findByName("totalEnergyConsumed")
|
readonly property bool isConsumer: root.thing && root.thing.thingClass.interfaces.indexOf("smartmeterconsumer") >= 0
|
||||||
readonly property State totalEnergyProducedState: root.thing.stateByName("totalEnergyProduced")
|
readonly property bool isProducer: root.thing && root.thingClass.interfaces.indexOf("smartmeterproducer") >= 0
|
||||||
readonly property StateType totalEnergyProducedStateType: root.thing.thingClass.stateTypes.findByName("totalEnergyProduced")
|
readonly property bool isBattery: root.thing && root.thingClass.interfaces.indexOf("energystorage") >= 0
|
||||||
|
|
||||||
Flickable {
|
|
||||||
|
readonly property State currentPowerState: root.thing.stateByName("currentPower")
|
||||||
|
|
||||||
|
// meters, producers, consumers
|
||||||
|
readonly property State totalEnergyConsumedState: isEnergyMeter || isConsumer ? root.thing.stateByName("totalEnergyConsumed") : null
|
||||||
|
readonly property StateType totalEnergyConsumedStateType: isEnergyMeter || isConsumer ? root.thing.thingClass.stateTypes.findByName("totalEnergyConsumed") : null
|
||||||
|
readonly property State totalEnergyProducedState: isEnergyMeter || isProducer ? root.thing.stateByName("totalEnergyProduced") : null
|
||||||
|
readonly property StateType totalEnergyProducedStateType: isEnergyMeter || isProducer ? root.thing.thingClass.stateTypes.findByName("totalEnergyProduced") : null
|
||||||
|
|
||||||
|
// Battery related states
|
||||||
|
readonly property State batteryLevelState: isBattery ? root.thing.stateByName("batteryLevel") : null
|
||||||
|
readonly property State batteryCriticalState: isBattery ? root.thing.stateByName("batteryCritical") : null
|
||||||
|
readonly property State chargingState: isBattery ? root.thing.stateByName("chargingState") : null
|
||||||
|
readonly property State capacityState: isBattery ? root.thing.stateByName("capacity") : null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
readonly property real currentPower: currentPowerState ? currentPowerState.value : 0
|
||||||
|
|
||||||
|
readonly property date now: d.now
|
||||||
|
readonly property date startTime: new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property date now: new Date()
|
||||||
|
}
|
||||||
|
Timer {
|
||||||
|
interval: 60000
|
||||||
|
repeat: true
|
||||||
|
running: true
|
||||||
|
onTriggered: d.now = new Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: contentGrid
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
topMargin: app.margins / 2
|
columns: app.landscape ? 2 : 1
|
||||||
contentHeight: contentGrid.height
|
|
||||||
interactive: contentHeight > height
|
|
||||||
|
|
||||||
GridLayout {
|
CircleBackground {
|
||||||
id: contentGrid
|
id: background
|
||||||
width: parent.width - app.margins
|
Layout.fillWidth: true
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.preferredHeight: width
|
||||||
columns: 1
|
Layout.leftMargin: app.landscape ? Style.margins : Style.hugeMargins
|
||||||
|
Layout.rightMargin: Style.hugeMargins
|
||||||
|
Layout.topMargin: Style.hugeMargins
|
||||||
|
Layout.bottomMargin: app.landscape ? Style.hugeMargins : Style.margins
|
||||||
|
iconSource: ""
|
||||||
|
onColor: batteryLevelState
|
||||||
|
? currentPower < 0 ? "crimson" : "limegreen"
|
||||||
|
: currentPower < 0 ? "limegreen" : "crimson"
|
||||||
|
|
||||||
BigTile {
|
Rectangle {
|
||||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
id: mask
|
||||||
showHeader: true
|
anchors.centerIn: parent
|
||||||
header: Label {
|
width: background.contentItem.width
|
||||||
text: qsTr("Total energy consumption")
|
height: background.contentItem.height
|
||||||
}
|
radius: width / 2
|
||||||
|
visible: false
|
||||||
onPressAndHold: {
|
|
||||||
var contextMenuComponent = Qt.createComponent("../components/ThingContextMenu.qml");
|
|
||||||
var contextMenu = contextMenuComponent.createObject(root, { thing: root.thing })
|
|
||||||
contextMenu.x = Qt.binding(function() { return (root.width - contextMenu.width) / 2 })
|
|
||||||
contextMenu.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: RowLayout {
|
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredHeight: Style.iconSize
|
|
||||||
Layout.preferredWidth: Style.iconSize
|
|
||||||
name: app.stateIcon("totalEnergyConsumed")
|
|
||||||
color: app.stateColor("totalEnergyConsumed")
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: root.totalEnergyConsumedState.value.toFixed(2) + " " + root.totalEnergyConsumedStateType.unitString
|
|
||||||
font.pixelSize: app.largeFont
|
|
||||||
}
|
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredHeight: Style.iconSize
|
|
||||||
Layout.preferredWidth: Style.iconSize
|
|
||||||
name: app.stateIcon("totalEnergyProduced")
|
|
||||||
color: app.stateColor("totalEnergyProduced")
|
|
||||||
visible: root.totalEnergyProducedState !== null
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: root.totalEnergyProducedState.value.toFixed(2) + " " + root.totalEnergyProducedStateType.unitString
|
|
||||||
font.pixelSize: app.largeFont
|
|
||||||
visible: root.totalEnergyProducedState !== null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericTypeGraph {
|
Item {
|
||||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
id: juice
|
||||||
thing: root.thing
|
anchors.fill: parent
|
||||||
stateType: root.thingClass.stateTypes.findByName("currentPower")
|
|
||||||
color: app.stateColor("currentPower")
|
Rectangle {
|
||||||
iconSource: app.stateIcon("currentPower")
|
anchors.centerIn: parent
|
||||||
roundTo: 5
|
width: background.contentItem.width
|
||||||
|
height: background.contentItem.height
|
||||||
|
property real progress: root.batteryLevelState ? root.batteryLevelState.value / 100 : 0
|
||||||
|
anchors.verticalCenterOffset: height * (1 - progress)
|
||||||
|
color: batteryCriticalState && batteryCriticalState.value ? "crimson" : "limegreen"
|
||||||
|
visible: root.batteryLevelState
|
||||||
|
}
|
||||||
|
|
||||||
|
RadialGradient {
|
||||||
|
id: gradient
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: background.contentItem.width
|
||||||
|
height: background.contentItem.height
|
||||||
|
property real progress: Math.abs(root.currentPower) / 10000
|
||||||
|
visible: currentPower != 0
|
||||||
|
|
||||||
|
Behavior on gradientRatio { NumberAnimation { duration: Style.sleepyAnimationDuration; easing.type: Easing.InOutQuad } }
|
||||||
|
property real gradientRatio: (1 - progress) * 0.1
|
||||||
|
gradient: Gradient{
|
||||||
|
GradientStop { position: .399 + gradient.gradientRatio; color: "transparent" }
|
||||||
|
GradientStop { position: .5; color: background.onColor }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font: Style.hugeFont
|
||||||
|
property bool toKilos: currentPower >= 1000
|
||||||
|
property double value: Math.abs(currentPower / (toKilos ? 1000 : 1))
|
||||||
|
text: "%1 %2".arg(value.toFixed(toKilos ? 2 : 1)).arg(toKilos ? "kW" : "W")
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: {
|
||||||
|
if (root.chargingState) {
|
||||||
|
switch (root.chargingState.value) {
|
||||||
|
case "idle":
|
||||||
|
return qsTr("Idle")
|
||||||
|
case "charging":
|
||||||
|
return qsTr("Charging")
|
||||||
|
case "discharging":
|
||||||
|
return qsTr("Discharging")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (root.isProducer) {
|
||||||
|
return qsTr("Production")
|
||||||
|
}
|
||||||
|
return root.currentPower < 0 ? qsTr("Return") : qsTr("Consumption")
|
||||||
|
}
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font: Style.hugeFont
|
||||||
|
visible: batteryLevelState
|
||||||
|
text: "%1 %".arg(batteryLevelState ? batteryLevelState.value : "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OpacityMask {
|
||||||
|
anchors.fill: background
|
||||||
|
source: ShaderEffectSource {
|
||||||
|
sourceItem: juice
|
||||||
|
hideSource: true
|
||||||
|
}
|
||||||
|
maskSource: mask
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: Style.bigMargins
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: textLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: isBattery
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
textFormat: Text.RichText
|
||||||
|
property bool isCharging: root.chargingState && root.chargingState.value === "charging"
|
||||||
|
property bool isDischarging: root.chargingState && root.chargingState.value === "discharging"
|
||||||
|
property double availableWh: isBattery ? root.capacityState.value * 1000 * root.batteryLevelState.value / 100 : 0
|
||||||
|
property double remainingWh: isCharging ? root.capacityState.value - availableWh : availableWh
|
||||||
|
property double remainingHours: isBattery ? remainingWh / Math.abs(root.currentPower) : 0
|
||||||
|
property date endTime: isBattery ? new Date(new Date().getTime() + remainingHours * 60 * 60 * 1000) : new Date()
|
||||||
|
property int n: Math.round(remainingHours)
|
||||||
|
|
||||||
|
text: isCharging ? qsTr("At the current rate, the battery will be fully charged at %1.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + endTime.toLocaleTimeString(Locale.ShortFormat) + "</span>")
|
||||||
|
: isDischarging ? qsTr("At the current rate, the battery will last until %1.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + endTime.toLocaleTimeString(Locale.ShortFormat) + "</span>")
|
||||||
|
: qsTr("The battery is fully charged")
|
||||||
|
}
|
||||||
|
|
||||||
|
BlurredLabel {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
visible: isEnergyMeter || isConsumer
|
||||||
|
blurred: periodConsumptionModel.busy
|
||||||
|
text: isConsumer ?
|
||||||
|
qsTr("A total of %1 kWh has been <b>consumed</b> in the last 24 hours.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + (totalPeriodConsumption).toFixed(1) + '</span>')
|
||||||
|
: qsTr("A total of %1 kWh has been <b>obtained</b> in the last 24 hours.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + (totalPeriodConsumption).toFixed(1) + '</span>')
|
||||||
|
textFormat: Text.RichText
|
||||||
|
|
||||||
|
LogsModel {
|
||||||
|
id: periodConsumptionModel
|
||||||
|
objectName: "Root meter model"
|
||||||
|
engine: root.isEnergyMeter ? _engine : null
|
||||||
|
thingId: root.thing.id
|
||||||
|
typeIds: isEnergyMeter ? [root.totalEnergyConsumedStateType.id] : []
|
||||||
|
viewStartTime: root.startTime
|
||||||
|
live: true
|
||||||
|
}
|
||||||
|
property LogEntry logEntryAtStart: periodConsumptionModel.busy ? null : periodConsumptionModel.findClosest(periodConsumptionModel.viewStartTime)
|
||||||
|
property double totalPeriodConsumption: logEntryAtStart && totalEnergyConsumedState ? totalEnergyConsumedState.value - logEntryAtStart.value : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
BlurredLabel {
|
||||||
|
visible: isEnergyMeter || isProducer
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
blurred: periodProductionModel.busy
|
||||||
|
text: isProducer ?
|
||||||
|
qsTr("A total of %1 kWh has been <b>produced</b> in the last 24 hours.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + (totalPeriodProduction).toFixed(1) + '</span>')
|
||||||
|
: qsTr("A total of %1 kWh has been <b>returned</b> in the last 24 hours.").arg('<span style="font-size:' + Style.bigFont.pixelSize + 'px">' + (totalPeriodProduction).toFixed(1) + '</span>')
|
||||||
|
textFormat: Text.RichText
|
||||||
|
|
||||||
|
LogsModel {
|
||||||
|
id: periodProductionModel
|
||||||
|
engine: root.isEnergyMeter ? _engine : null
|
||||||
|
thingId: root.thing.id
|
||||||
|
typeIds: isEnergyMeter ? [root.totalEnergyProducedStateType.id] : []
|
||||||
|
viewStartTime: root.startTime
|
||||||
|
live: true
|
||||||
|
}
|
||||||
|
property LogEntry logEntryAtStart: periodProductionModel.busy ? null : periodProductionModel.findClosest(periodProductionModel.viewStartTime)
|
||||||
|
property double totalPeriodProduction: logEntryAtStart && totalEnergyProducedState ? totalEnergyProducedState.value - logEntryAtStart.value : 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user