More improvements on the energy view
Bring back title headers allow opening a single chart fullscreen allow selecting individual series in a chart
This commit is contained in:
parent
80f74e192f
commit
32853ce612
@ -281,5 +281,11 @@
|
|||||||
<file>ui/mainviews/energy/PowerBalanceHistory.qml</file>
|
<file>ui/mainviews/energy/PowerBalanceHistory.qml</file>
|
||||||
<file>ui/mainviews/energy/CurrentPowerBalancePieChart.qml</file>
|
<file>ui/mainviews/energy/CurrentPowerBalancePieChart.qml</file>
|
||||||
<file>ui/components/MultiSelectionTabs.qml</file>
|
<file>ui/components/MultiSelectionTabs.qml</file>
|
||||||
|
<file>ui/mainviews/energy/PowerBalanceHistoryPage.qml</file>
|
||||||
|
<file>ui/mainviews/energy/CurrentPowerBalancePage.qml</file>
|
||||||
|
<file>ui/mainviews/energy/PowerBalanceStatsPage.qml</file>
|
||||||
|
<file>ui/mainviews/energy/ConsumersHistoryPage.qml</file>
|
||||||
|
<file>ui/mainviews/energy/ConsumerStatsPage.qml</file>
|
||||||
|
<file>ui/mainviews/energy/ConsumersPieChartPage.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -142,7 +142,7 @@ ApplicationWindow {
|
|||||||
property NymeaDiscovery nymeaDiscovery: NymeaDiscovery {
|
property NymeaDiscovery nymeaDiscovery: NymeaDiscovery {
|
||||||
objectName: "discovery"
|
objectName: "discovery"
|
||||||
awsClient: AWSClient
|
awsClient: AWSClient
|
||||||
bluetoothDiscoveryEnabled: PlatformPermissions.bluetoothPermission === PlatformPermissions.PermissionStatusGranted
|
bluetoothDiscoveryEnabled: false// PlatformPermissions.bluetoothPermission === PlatformPermissions.PermissionStatusGranted
|
||||||
}
|
}
|
||||||
|
|
||||||
property var supportedInterfaces: [
|
property var supportedInterfaces: [
|
||||||
|
|||||||
@ -60,8 +60,6 @@ MainViewBase {
|
|||||||
engine: _engine
|
engine: _engine
|
||||||
}
|
}
|
||||||
|
|
||||||
property var thingColors: [Style.blue, Style.green, Style.red, Style.yellow, Style.purple, Style.orange, Style.lime, Style.pink, Style.darkBlue]
|
|
||||||
|
|
||||||
|
|
||||||
ThingsProxy {
|
ThingsProxy {
|
||||||
id: energyMeters
|
id: energyMeters
|
||||||
@ -169,7 +167,6 @@ MainViewBase {
|
|||||||
Layout.preferredHeight: width
|
Layout.preferredHeight: width
|
||||||
energyManager: energyManager
|
energyManager: energyManager
|
||||||
visible: consumers.count > 0
|
visible: consumers.count > 0
|
||||||
colors: root.thingColors
|
|
||||||
consumers: consumers
|
consumers: consumers
|
||||||
animationsEnabled: Qt.application.active && root.isCurrentItem && flickable.contentY < y + height && flickable.contentY + flickable.height > y
|
animationsEnabled: Qt.application.active && root.isCurrentItem && flickable.contentY < y + height && flickable.contentY + flickable.height > y
|
||||||
onAnimationsEnabledChanged: print("animations for consumer balance chart", animationsEnabled ? "enabled" : "disabled")
|
onAnimationsEnabledChanged: print("animations for consumer balance chart", animationsEnabled ? "enabled" : "disabled")
|
||||||
@ -180,7 +177,7 @@ MainViewBase {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: width
|
Layout.preferredHeight: width
|
||||||
visible: consumers.count > 0
|
visible: consumers.count > 0
|
||||||
colors: root.thingColors
|
energyManager: energyManager
|
||||||
consumers: consumers
|
consumers: consumers
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +186,6 @@ MainViewBase {
|
|||||||
Layout.preferredHeight: width
|
Layout.preferredHeight: width
|
||||||
energyManager: energyManager
|
energyManager: energyManager
|
||||||
visible: consumers.count > 0
|
visible: consumers.count > 0
|
||||||
colors: root.thingColors
|
|
||||||
consumers: consumers
|
consumers: consumers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,8 @@ StatsBase {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property EnergyManager energyManager: null
|
property EnergyManager energyManager: null
|
||||||
property var colors: null
|
|
||||||
|
|
||||||
property ThingsProxy consumers: null
|
property ThingsProxy consumers: null
|
||||||
|
property bool titleVisible: true
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
@ -20,6 +19,8 @@ StatsBase {
|
|||||||
|
|
||||||
property int startOffset: 0
|
property int startOffset: 0
|
||||||
|
|
||||||
|
property Thing selectedThing: null
|
||||||
|
|
||||||
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
|
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
|
||||||
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
|
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
|
||||||
|
|
||||||
@ -45,6 +46,14 @@ StatsBase {
|
|||||||
consumersRepeater.itemAt(i).refresh()
|
consumersRepeater.itemAt(i).refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectThing(thing) {
|
||||||
|
if (d.selectedThing === thing) {
|
||||||
|
d.selectedThing = null
|
||||||
|
} else {
|
||||||
|
d.selectedThing = thing
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThingPowerLogsLoader {
|
ThingPowerLogsLoader {
|
||||||
@ -146,9 +155,11 @@ StatsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
barSet = barSeries.append(consumerDelegate.thing.name, values)
|
barSet = barSeries.append(consumerDelegate.thing.name, values)
|
||||||
barSet.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
|
barSet.color = Qt.binding(function() {
|
||||||
barSet.borderColor = barSet.color
|
return NymeaUtils.generateColor(Style.generationBaseColor, index, d.selectedThing == null || consumerDelegate.thing == d.selectedThing ? 1 : 0.3)
|
||||||
barSet.borderWith = 0
|
})
|
||||||
|
barSet.borderColor = Qt.binding(function(){ return barSet.color})
|
||||||
|
barSet.borderWidth = 0
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
barSeries.remove(barSet)
|
barSeries.remove(barSet)
|
||||||
@ -160,12 +171,17 @@ StatsBase {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
// Label {
|
Label {
|
||||||
// Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
// Layout.margins: Style.smallMargins
|
Layout.margins: Style.smallMargins
|
||||||
// horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// text: qsTr("Consumers totals")
|
text: qsTr("Consumers totals")
|
||||||
// }
|
visible: root.titleVisible
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("ConsumerStatsPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SelectionTabs {
|
SelectionTabs {
|
||||||
id: selectionTabs
|
id: selectionTabs
|
||||||
@ -311,6 +327,7 @@ StatsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: legend
|
||||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
||||||
anchors.leftMargin: chartView.plotArea.x
|
anchors.leftMargin: chartView.plotArea.x
|
||||||
height: Style.smallIconSize
|
height: Style.smallIconSize
|
||||||
@ -318,17 +335,30 @@ StatsBase {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.consumers
|
model: root.consumers
|
||||||
delegate: Item {
|
delegate: MouseArea {
|
||||||
id: legendDelegate
|
id: legendDelegate
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
readonly property Thing thing: root.consumers.get(index)
|
readonly property Thing thing: root.consumers.get(index)
|
||||||
ColorIcon {
|
onClicked: d.selectThing(thing)
|
||||||
name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
|
Row {
|
||||||
size: Style.smallIconSize
|
|
||||||
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.smallMargins
|
||||||
|
ColorIcon {
|
||||||
|
name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: legendDelegate.thing.name
|
||||||
|
width: Math.max(0, legendDelegate.width - x)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: Style.smallFont
|
||||||
|
visible: legend.width / root.consumers.count >= 80
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,7 +526,7 @@ StatsBase {
|
|||||||
var consumerDelegate = consumersRepeater.itemAt(i)
|
var consumerDelegate = consumersRepeater.itemAt(i)
|
||||||
var consumer = consumerDelegate.thing
|
var consumer = consumerDelegate.thing
|
||||||
var entry = {
|
var entry = {
|
||||||
name: consumer.name,
|
consumer: consumer,
|
||||||
value: consumersRepeater.itemAt(i).barSet.at(toolTip.idx).toFixed(2),
|
value: consumersRepeater.itemAt(i).barSet.at(toolTip.idx).toFixed(2),
|
||||||
indexInModel: i
|
indexInModel: i
|
||||||
}
|
}
|
||||||
@ -518,14 +548,14 @@ StatsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
|
opacity: d.selectedThing == null || d.selectedThing === model.consumer ? 1 : 0.3
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: Style.extraSmallFont.pixelSize
|
width: Style.extraSmallFont.pixelSize
|
||||||
height: width
|
height: width
|
||||||
// color: root.colors[model.indexInModel % root.colors.length]
|
|
||||||
color: NymeaUtils.generateColor(Style.generationBaseColor, model.indexInModel)
|
color: NymeaUtils.generateColor(Style.generationBaseColor, model.indexInModel)
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: "%1: %2 kWh".arg(model.name).arg(model.value)
|
text: "%1: %2 kWh".arg(model.consumer.name).arg(model.value)
|
||||||
font: Style.extraSmallFont
|
font: Style.extraSmallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
nymea-app/ui/mainviews/energy/ConsumerStatsPage.qml
Normal file
24
nymea-app/ui/mainviews/energy/ConsumerStatsPage.qml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias energyManager: consumersStats
|
||||||
|
property alias consumers: consumersStats.consumers
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Consumers balance")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsumerStats {
|
||||||
|
id: consumersStats
|
||||||
|
anchors.fill: parent
|
||||||
|
titleVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,8 +8,9 @@ import "qrc:/ui/components"
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var colors: null
|
property EnergyManager energyManager: null
|
||||||
property ThingsProxy consumers: null
|
property ThingsProxy consumers: null
|
||||||
|
property bool titleVisible: true
|
||||||
|
|
||||||
PowerBalanceLogs {
|
PowerBalanceLogs {
|
||||||
id: powerBalanceLogs
|
id: powerBalanceLogs
|
||||||
@ -53,6 +54,8 @@ Item {
|
|||||||
|
|
||||||
property date now: new Date()
|
property date now: new Date()
|
||||||
|
|
||||||
|
property var selectedSeries: null
|
||||||
|
|
||||||
readonly property int range: selectionTabs.currentValue.range
|
readonly property int range: selectionTabs.currentValue.range
|
||||||
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
|
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
|
||||||
readonly property int visibleValues: range / sampleRate
|
readonly property int visibleValues: range / sampleRate
|
||||||
@ -95,6 +98,15 @@ Item {
|
|||||||
logsLoader.fetchLogs();
|
logsLoader.fetchLogs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectSeries(series) {
|
||||||
|
print("selecting series", series)
|
||||||
|
if (d.selectedSeries === series) {
|
||||||
|
d.selectedSeries = null
|
||||||
|
} else {
|
||||||
|
d.selectedSeries = series
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@ -111,12 +123,17 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
// Label {
|
Label {
|
||||||
// Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
// Layout.margins: Style.smallMargins
|
Layout.margins: Style.smallMargins
|
||||||
// horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// text: qsTr("Consumers history")
|
text: qsTr("Consumers history")
|
||||||
// }
|
visible: root.titleVisible
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("ConsumersHistoryPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SelectionTabs {
|
SelectionTabs {
|
||||||
id: selectionTabs
|
id: selectionTabs
|
||||||
@ -456,8 +473,11 @@ Item {
|
|||||||
series.lowerSeries = lineSeriesComponent.createObject(series)
|
series.lowerSeries = lineSeriesComponent.createObject(series)
|
||||||
series.upperSeries = lineSeriesComponent.createObject(series)
|
series.upperSeries = lineSeriesComponent.createObject(series)
|
||||||
series.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
|
series.color = NymeaUtils.generateColor(Style.generationBaseColor, index)
|
||||||
|
series.opacity = Qt.binding(function() {
|
||||||
|
return d.selectedSeries == null || d.selectedSeries == series ? 1 : 0.3
|
||||||
|
})
|
||||||
series.borderWidth = 0;
|
series.borderWidth = 0;
|
||||||
series.borderColor = series.color
|
series.borderColor = series.color
|
||||||
|
|
||||||
// Add a first point at 0 value
|
// Add a first point at 0 value
|
||||||
series.lowerSeries.insert(0, new Date().getTime(), 0)
|
series.lowerSeries.insert(0, new Date().getTime(), 0)
|
||||||
@ -472,6 +492,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: legend
|
||||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
||||||
anchors.leftMargin: chartView.plotArea.x
|
anchors.leftMargin: chartView.plotArea.x
|
||||||
height: Style.smallIconSize
|
height: Style.smallIconSize
|
||||||
@ -479,23 +500,34 @@ Item {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.consumers
|
model: root.consumers
|
||||||
delegate: Item {
|
delegate: MouseArea {
|
||||||
id: legendDelegate
|
id: legendDelegate
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
readonly property Thing thing: root.consumers.get(index)
|
readonly property Thing thing: root.consumers.get(index)
|
||||||
ColorIcon {
|
onClicked: d.selectSeries(consumersRepeater.itemAt(index).series)
|
||||||
name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
|
opacity: d.selectedSeries == null || d.selectedSeries === consumersRepeater.itemAt(index).series ? 1 : 0.3
|
||||||
size: Style.smallIconSize
|
Row {
|
||||||
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.smallMargins
|
||||||
|
ColorIcon {
|
||||||
|
name: app.interfacesToIcon(legendDelegate.thing.thingClass.interfaces)
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: legendDelegate.thing.name
|
||||||
|
width: Math.max(0, legendDelegate.width - x)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font: Style.smallFont
|
||||||
|
visible: legend.width / root.consumers.count >= 80
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -665,20 +697,21 @@ Item {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: consumersRepeater.count
|
model: consumersRepeater.count
|
||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
|
readonly property Item chartItem: consumersRepeater.itemAt(index)
|
||||||
id: consumerToolTipDelegate
|
id: consumerToolTipDelegate
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries === chartItem.series ? 1 : 0.3
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: Style.extraSmallFont.pixelSize
|
width: Style.extraSmallFont.pixelSize
|
||||||
height: width
|
height: width
|
||||||
// color: index >= 0 ? root.colors[index % root.colors.length] : "white"
|
|
||||||
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
color: index >= 0 ? NymeaUtils.generateColor(Style.generationBaseColor, index) : "white"
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
property ThingPowerLogEntry entry: toolTip.idx >= 0 ? consumersRepeater.itemAt(index).logs.find(toolTip.timestamp) : null
|
property ThingPowerLogEntry entry: toolTip.idx >= 0 ? chartItem.logs.find(toolTip.timestamp) : null
|
||||||
property double rawValue: entry ? entry.currentPower : 0
|
property double rawValue: entry ? entry.currentPower : 0
|
||||||
property double displayValue: rawValue >= 1000 ? rawValue / 1000 : rawValue
|
property double displayValue: rawValue >= 1000 ? rawValue / 1000 : rawValue
|
||||||
property string unit: rawValue >= 1000 ? "kW" : "W"
|
property string unit: rawValue >= 1000 ? "kW" : "W"
|
||||||
text: "%1: %2 %3".arg(consumersRepeater.itemAt(index).thing.name).arg(displayValue.toFixed(2)).arg(unit)
|
text: "%1: %2 %3".arg(chartItem.thing.name).arg(displayValue.toFixed(2)).arg(unit)
|
||||||
font: Style.extraSmallFont
|
font: Style.extraSmallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
nymea-app/ui/mainviews/energy/ConsumersHistoryPage.qml
Normal file
24
nymea-app/ui/mainviews/energy/ConsumersHistoryPage.qml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias energyManager: consumersHistory
|
||||||
|
property alias consumers: consumersHistory.consumers
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Power balance totals")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsumersHistory {
|
||||||
|
id: consumersHistory
|
||||||
|
anchors.fill: parent
|
||||||
|
titleVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,23 +7,13 @@ import QtCharts 2.2
|
|||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
import "qrc:/ui/components"
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
ChartView {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
backgroundColor: "transparent"
|
|
||||||
animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
|
||||||
// title: qsTr("Consumers balance")
|
|
||||||
titleColor: Style.foregroundColor
|
|
||||||
legend.visible: false
|
|
||||||
|
|
||||||
margins.left: 0
|
|
||||||
margins.right: 0
|
|
||||||
margins.bottom: 0
|
|
||||||
margins.top: 0
|
|
||||||
|
|
||||||
property EnergyManager energyManager: null
|
property EnergyManager energyManager: null
|
||||||
property ThingsProxy consumers: null
|
property ThingsProxy consumers: null
|
||||||
property var colors: null
|
|
||||||
property bool animationsEnabled: true
|
property bool animationsEnabled: true
|
||||||
|
property bool titleVisible: true
|
||||||
|
|
||||||
readonly property Thing rootMeter: engine.thingManager.fetchingData ? null : engine.thingManager.things.getThing(energyManager.rootMeterId)
|
readonly property Thing rootMeter: engine.thingManager.fetchingData ? null : engine.thingManager.things.getThing(energyManager.rootMeterId)
|
||||||
onRootMeterChanged: updateConsumers()
|
onRootMeterChanged: updateConsumers()
|
||||||
@ -72,7 +62,7 @@ ChartView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateConsumers() {
|
function updateConsumers() {
|
||||||
root.animationOptions = ChartView.NoAnimation
|
chart.animationOptions = ChartView.NoAnimation
|
||||||
consumersBalanceSeries.clear();
|
consumersBalanceSeries.clear();
|
||||||
d.unknownSlice = null
|
d.unknownSlice = null
|
||||||
d.idleSlice = null
|
d.idleSlice = null
|
||||||
@ -115,131 +105,164 @@ ChartView {
|
|||||||
|
|
||||||
d.thingsColorMap = colorMap
|
d.thingsColorMap = colorMap
|
||||||
|
|
||||||
root.animationOptions = Qt.binding(function() {
|
chart.animationOptions = Qt.binding(function() {
|
||||||
return root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
return root.animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
PieSeries {
|
Label {
|
||||||
id: consumersBalanceSeries
|
id: titleLabel
|
||||||
size: 0.88
|
anchors { left: parent.left; top: parent.top; right: parent.right; margins: Style.smallMargins }
|
||||||
holeSize: 0.7
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: qsTr("Consumers balance")
|
||||||
|
visible: root.titleVisible
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
pageStack.push(Qt.resolvedUrl("ConsumersPieChartPage.qml"), {energyManager: root.energyManager, consumers: root.consumers})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Flickable {
|
|
||||||
id: centerLayout
|
|
||||||
x: root.plotArea.x + (root.plotArea.width - width) / 2
|
|
||||||
y: root.plotArea.y + (root.plotArea.height - height) / 2
|
|
||||||
width: Math.min(root.plotArea.width, root.plotArea.width) * 0.65
|
|
||||||
height: Math.min(contentColumn.height + topMargin + bottomMargin, width)
|
|
||||||
topMargin: Style.smallIconSize
|
|
||||||
bottomMargin: Style.smallIconSize
|
|
||||||
opacity: 0
|
|
||||||
// property int maximumHeight: root.plotArea.height * 0.65
|
|
||||||
|
|
||||||
contentHeight: contentColumn.implicitHeight
|
ChartView {
|
||||||
|
id: chart
|
||||||
|
|
||||||
ColumnLayout {
|
anchors { left: parent.left; right: parent.right; bottom: parent.bottom; top: titleLabel.bottom}
|
||||||
id: contentColumn
|
|
||||||
width: parent.width
|
backgroundColor: "transparent"
|
||||||
spacing: Style.smallMargins
|
animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
||||||
|
titleColor: Style.foregroundColor
|
||||||
|
legend.visible: false
|
||||||
|
|
||||||
|
margins.left: 0
|
||||||
|
margins.right: 0
|
||||||
|
margins.bottom: 0
|
||||||
|
margins.top: 0
|
||||||
|
|
||||||
|
|
||||||
|
PieSeries {
|
||||||
|
id: consumersBalanceSeries
|
||||||
|
size: 0.88
|
||||||
|
holeSize: 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: centerLayout
|
||||||
|
x: chart.plotArea.x + (chart.plotArea.width - width) / 2
|
||||||
|
y: chart.plotArea.y + (chart.plotArea.height - height) / 2
|
||||||
|
width: Math.min(chart.plotArea.width, chart.plotArea.width) * 0.65
|
||||||
|
height: Math.min(contentColumn.height + topMargin + bottomMargin, width)
|
||||||
|
topMargin: Style.smallIconSize
|
||||||
|
bottomMargin: Style.smallIconSize
|
||||||
|
opacity: 0
|
||||||
|
// property int maximumHeight: chart.plotArea.height * 0.65
|
||||||
|
|
||||||
|
contentHeight: contentColumn.implicitHeight
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
id: contentColumn
|
||||||
spacing: 0
|
width: parent.width
|
||||||
visible: root.rootMeter
|
spacing: Style.smallMargins
|
||||||
Label {
|
|
||||||
text: qsTr("Total")
|
ColumnLayout {
|
||||||
font: Style.smallFont
|
|
||||||
Layout.topMargin: Style.smallMargins
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
// We're using the maximum value of the energy managers consumption, the sum of all consumers because:
|
|
||||||
// * in a standard setup, the energy manager would know everything and the consumption will always be greater than the sum of all individual consumers
|
|
||||||
// * if there is a producer which is unknown to nymea though, it will decrease the consumption on the root meter so it may be smaller than the
|
|
||||||
// summation of all consumers. In this particular chart that would be nonsense so in the end we'll only lose the "unknown" power consumption in such a setup
|
|
||||||
property double finalTotal: Math.max(energyManager.currentPowerConsumption, d.consumersSummation)
|
|
||||||
text: "%1 %2"
|
|
||||||
.arg((finalTotal / (finalTotal > 1000 ? 1000 : 1)).toFixed(1))
|
|
||||||
.arg(finalTotal > 1000 ? "kW" : "W")
|
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
font: Style.bigFont
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: ThingsProxy {
|
|
||||||
id: sortedConsumers
|
|
||||||
engine: _engine
|
|
||||||
parentProxy: root.consumers
|
|
||||||
sortStateName: "currentPower"
|
|
||||||
sortOrder: Qt.DescendingOrder
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: ColumnLayout {
|
|
||||||
id: consumerDelegate
|
|
||||||
width: parent ? parent.width : 0
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
property Thing consumer: consumers.getThing(model.id)
|
visible: root.rootMeter
|
||||||
property State currentPowerState: consumer ? consumer.stateByName("currentPower") : null
|
Label {
|
||||||
property double value: currentPowerState ? currentPowerState.value : 0
|
text: qsTr("Total")
|
||||||
|
font: Style.smallFont
|
||||||
|
Layout.topMargin: Style.smallMargins
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: model.name
|
// We're using the maximum value of the energy managers consumption, the sum of all consumers because:
|
||||||
Layout.fillWidth: true
|
// * in a standard setup, the energy manager would know everything and the consumption will always be greater than the sum of all individual consumers
|
||||||
horizontalAlignment: Text.AlignHCenter
|
// * if there is a producer which is unknown to nymea though, it will decrease the consumption on the root meter so it may be smaller than the
|
||||||
font: Style.extraSmallFont
|
// summation of all consumers. In this particular chart that would be nonsense so in the end we'll only lose the "unknown" power consumption in such a setup
|
||||||
}
|
property double finalTotal: Math.max(energyManager.currentPowerConsumption, d.consumersSummation)
|
||||||
Label {
|
|
||||||
color: d.thingsColorMap.hasOwnProperty(consumer) ? d.thingsColorMap[consumer] : "transparent"
|
|
||||||
text: "%1 %2"
|
text: "%1 %2"
|
||||||
.arg((consumerDelegate.value / (consumerDelegate.value > 1000 ? 1000 : 1)).toFixed(1))
|
.arg((finalTotal / (finalTotal > 1000 ? 1000 : 1)).toFixed(1))
|
||||||
.arg(consumerDelegate.value > 1000 ? "kW" : "W")
|
.arg(finalTotal > 1000 ? "kW" : "W")
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
font: Style.smallFont
|
font: Style.bigFont
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ThingsProxy {
|
||||||
|
id: sortedConsumers
|
||||||
|
engine: _engine
|
||||||
|
parentProxy: root.consumers
|
||||||
|
sortStateName: "currentPower"
|
||||||
|
sortOrder: Qt.DescendingOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: ColumnLayout {
|
||||||
|
id: consumerDelegate
|
||||||
|
width: parent ? parent.width : 0
|
||||||
|
spacing: 0
|
||||||
|
property Thing consumer: consumers.getThing(model.id)
|
||||||
|
property State currentPowerState: consumer ? consumer.stateByName("currentPower") : null
|
||||||
|
property double value: currentPowerState ? currentPowerState.value : 0
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: model.name
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font: Style.extraSmallFont
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
color: d.thingsColorMap.hasOwnProperty(consumer) ? d.thingsColorMap[consumer] : "transparent"
|
||||||
|
text: "%1 %2"
|
||||||
|
.arg((consumerDelegate.value / (consumerDelegate.value > 1000 ? 1000 : 1)).toFixed(1))
|
||||||
|
.arg(consumerDelegate.value > 1000 ? "kW" : "W")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Rectangle {
|
||||||
|
id: innerMask
|
||||||
Rectangle {
|
anchors.fill: centerLayout
|
||||||
id: innerMask
|
radius: width / 2
|
||||||
anchors.fill: centerLayout
|
visible: false
|
||||||
radius: width / 2
|
gradient: Gradient {
|
||||||
visible: false
|
GradientStop { position: 0; color: "transparent" }
|
||||||
gradient: Gradient {
|
GradientStop { position: 1-(centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
|
||||||
GradientStop { position: 0; color: "transparent" }
|
GradientStop { position: (centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
|
||||||
GradientStop { position: 1-(centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
|
GradientStop { position: 1; color: "transparent" }
|
||||||
GradientStop { position: (centerLayout.height - downArrow.height * 1.5) / centerLayout.height; color: "red" }
|
}
|
||||||
GradientStop { position: 1; color: "transparent" }
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
OpacityMask {
|
OpacityMask {
|
||||||
anchors.fill: centerLayout
|
anchors.fill: centerLayout
|
||||||
source: centerLayout
|
source: centerLayout
|
||||||
maskSource: innerMask
|
maskSource: innerMask
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
id: upArrow
|
id: upArrow
|
||||||
anchors { top: centerLayout.top; horizontalCenter: centerLayout.horizontalCenter }
|
anchors { top: centerLayout.top; horizontalCenter: centerLayout.horizontalCenter }
|
||||||
size: Style.smallIconSize
|
size: Style.smallIconSize
|
||||||
name: "up"
|
name: "up"
|
||||||
visible: !centerLayout.atYBeginning
|
visible: !centerLayout.atYBeginning
|
||||||
}
|
}
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
id: downArrow
|
id: downArrow
|
||||||
anchors { bottom: centerLayout.bottom; horizontalCenter: centerLayout.horizontalCenter }
|
anchors { bottom: centerLayout.bottom; horizontalCenter: centerLayout.horizontalCenter }
|
||||||
size: Style.smallIconSize
|
size: Style.smallIconSize
|
||||||
name: "down"
|
name: "down"
|
||||||
visible: !centerLayout.atYEnd
|
visible: !centerLayout.atYEnd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
nymea-app/ui/mainviews/energy/ConsumersPieChartPage.qml
Normal file
24
nymea-app/ui/mainviews/energy/ConsumersPieChartPage.qml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias energyManager: consumersPieChart.energyManager
|
||||||
|
property alias consumers: consumersPieChart.consumers
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Consumers balance")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsumersPieChart {
|
||||||
|
id: consumersPieChart
|
||||||
|
anchors.fill: parent
|
||||||
|
titleVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ ChartView {
|
|||||||
id: consumptionPieChart
|
id: consumptionPieChart
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
animationOptions: animationsEnabled ? NymeaUtils.chartsAnimationOptions : ChartView.NoAnimation
|
||||||
title: qsTr("My energy mix")
|
title: qsTr("My energy consumption")
|
||||||
titleColor: Style.foregroundColor
|
titleColor: Style.foregroundColor
|
||||||
legend.visible: false
|
legend.visible: false
|
||||||
|
|
||||||
|
|||||||
41
nymea-app/ui/mainviews/energy/CurrentPowerBalancePage.qml
Normal file
41
nymea-app/ui/mainviews/energy/CurrentPowerBalancePage.qml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property EnergyManager energyManager: null
|
||||||
|
property ThingsProxy consumers: null
|
||||||
|
property ThingsProxy producers: null
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("My energy mix")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
columns: app.landscape ? 2 : 1
|
||||||
|
|
||||||
|
CurrentConsumptionBalancePieChart {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
energyManager: root.energyManager
|
||||||
|
visible: root.producers.count > 0
|
||||||
|
animationsEnabled: Qt.application.active
|
||||||
|
}
|
||||||
|
CurrentProductionBalancePieChart {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
energyManager: root.energyManager
|
||||||
|
visible: root.producers.count > 0
|
||||||
|
animationsEnabled: Qt.application.active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,8 @@ import "qrc:/ui/components"
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property bool titleVisible: true
|
||||||
|
|
||||||
PowerBalanceLogs {
|
PowerBalanceLogs {
|
||||||
id: powerBalanceLogs
|
id: powerBalanceLogs
|
||||||
engine: _engine
|
engine: _engine
|
||||||
@ -26,6 +28,8 @@ Item {
|
|||||||
id: d
|
id: d
|
||||||
property date now: new Date()
|
property date now: new Date()
|
||||||
|
|
||||||
|
property var selectedSeries: null
|
||||||
|
|
||||||
readonly property int range: selectionTabs.currentValue.range
|
readonly property int range: selectionTabs.currentValue.range
|
||||||
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
|
readonly property int sampleRate: selectionTabs.currentValue.sampleRate
|
||||||
readonly property int visibleValues: range / sampleRate
|
readonly property int visibleValues: range / sampleRate
|
||||||
@ -63,6 +67,13 @@ Item {
|
|||||||
return timestamp
|
return timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectSeries(series) {
|
||||||
|
if (d.selectedSeries == series) {
|
||||||
|
d.selectedSeries = null
|
||||||
|
} else {
|
||||||
|
d.selectedSeries = series
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@ -105,12 +116,20 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
// Label {
|
Label {
|
||||||
// Layout.fillWidth: true
|
id: titleLabel
|
||||||
// Layout.margins: Style.smallMargins
|
Layout.fillWidth: true
|
||||||
// horizontalAlignment: Text.AlignHCenter
|
Layout.margins: Style.smallMargins
|
||||||
// text: qsTr("My production history")
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// }
|
text: qsTr("My power balance history")
|
||||||
|
visible: root.titleVisible
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
pageStack.push(Qt.resolvedUrl("PowerBalanceHistoryPage.qml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SelectionTabs {
|
SelectionTabs {
|
||||||
id: selectionTabs
|
id: selectionTabs
|
||||||
@ -265,6 +284,7 @@ Item {
|
|||||||
shadesVisible: false
|
shadesVisible: false
|
||||||
labelsColor: Style.foregroundColor
|
labelsColor: Style.foregroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
AreaSeries {
|
AreaSeries {
|
||||||
id: selfProductionConsumptionSeries
|
id: selfProductionConsumptionSeries
|
||||||
axisX: dateTimeAxis
|
axisX: dateTimeAxis
|
||||||
@ -273,8 +293,10 @@ Item {
|
|||||||
// borderWidth: 2
|
// borderWidth: 2
|
||||||
borderColor: color
|
borderColor: color
|
||||||
name: qsTr("From self production")
|
name: qsTr("From self production")
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries == selfProductionConsumptionSeries ? 1 : 0.3
|
||||||
// visible: false
|
// visible: false
|
||||||
|
|
||||||
|
onClicked: d.selectedSeries(selfProductionConsumptionSeries)
|
||||||
lowerSeries: LineSeries {
|
lowerSeries: LineSeries {
|
||||||
id: zeroSeries
|
id: zeroSeries
|
||||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||||
@ -331,9 +353,11 @@ Item {
|
|||||||
color: Style.purple
|
color: Style.purple
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
borderColor: color
|
borderColor: color
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries == toStorageSeries ? 1 : 0.3
|
||||||
visible: root.batteries.count > 0
|
visible: root.batteries.count > 0
|
||||||
name: qsTr("To battery")
|
name: qsTr("To battery")
|
||||||
|
|
||||||
|
onClicked: d.selectSeries(toStorageSeries)
|
||||||
|
|
||||||
function calculateValue(entry) {
|
function calculateValue(entry) {
|
||||||
return selfProductionConsumptionSeries.calculateValue(entry) + Math.max(0, entry.storage);
|
return selfProductionConsumptionSeries.calculateValue(entry) + Math.max(0, entry.storage);
|
||||||
@ -352,7 +376,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AreaSeries {
|
AreaSeries {
|
||||||
id: returnSeries
|
id: returnSeries
|
||||||
axisX: dateTimeAxis
|
axisX: dateTimeAxis
|
||||||
@ -361,8 +384,11 @@ Item {
|
|||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
borderColor: color
|
borderColor: color
|
||||||
name: qsTr("To grid")
|
name: qsTr("To grid")
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries == returnSeries ? 1 : 0.3
|
||||||
// visible: false
|
// visible: false
|
||||||
|
|
||||||
|
onClicked: d.selectSeries(returnSeries)
|
||||||
|
|
||||||
function calculateValue(entry) {
|
function calculateValue(entry) {
|
||||||
return toStorageSeries.calculateValue(entry) + Math.max(0, -entry.acquisition)
|
return toStorageSeries.calculateValue(entry) + Math.max(0, -entry.acquisition)
|
||||||
}
|
}
|
||||||
@ -387,8 +413,10 @@ Item {
|
|||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
borderColor: color
|
borderColor: color
|
||||||
name: qsTr("From battery")
|
name: qsTr("From battery")
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries == fromStorageSeries ? 1 : 0.3
|
||||||
visible: root.batteries.count > 0
|
visible: root.batteries.count > 0
|
||||||
|
|
||||||
|
onClicked: d.selectSeries(fromStorageSeries)
|
||||||
lowerSeries: selfProductionConsumptionUpperSeries
|
lowerSeries: selfProductionConsumptionUpperSeries
|
||||||
upperSeries: LineSeries {
|
upperSeries: LineSeries {
|
||||||
id: fromStorageUpperSeries
|
id: fromStorageUpperSeries
|
||||||
@ -406,7 +434,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AreaSeries {
|
AreaSeries {
|
||||||
id: acquisitionSeries
|
id: acquisitionSeries
|
||||||
axisX: dateTimeAxis
|
axisX: dateTimeAxis
|
||||||
@ -415,8 +442,11 @@ Item {
|
|||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
borderColor: color
|
borderColor: color
|
||||||
name: qsTr("From grid")
|
name: qsTr("From grid")
|
||||||
|
opacity: d.selectedSeries == null || d.selectedSeries == acquisitionSeries ? 1 : 0.3
|
||||||
// visible: false
|
// visible: false
|
||||||
|
|
||||||
|
onClicked: d.selectSeries(acquisitionSeries)
|
||||||
|
|
||||||
lowerSeries: fromStorageUpperSeries
|
lowerSeries: fromStorageUpperSeries
|
||||||
upperSeries: LineSeries {
|
upperSeries: LineSeries {
|
||||||
id: acquisitionUpperSeries
|
id: acquisitionUpperSeries
|
||||||
@ -476,89 +506,158 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: legend
|
||||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
||||||
anchors.leftMargin: chartView.plotArea.x
|
anchors.leftMargin: chartView.plotArea.x
|
||||||
height: Style.smallIconSize
|
height: Style.smallIconSize
|
||||||
anchors.margins: Style.margins
|
anchors.margins: Style.margins
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
ColorIcon {
|
onClicked: d.selectSeries(selfProductionConsumptionSeries)
|
||||||
name: "weathericons/weather-clear-day"
|
opacity: selfProductionConsumptionSeries.opacity
|
||||||
size: Style.smallIconSize
|
Row {
|
||||||
color: Style.green
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.smallMargins
|
||||||
|
ColorIcon {
|
||||||
|
name: "weathericons/weather-clear-day"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.green
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
width: parent.parent.width - x
|
||||||
|
elide: Text.ElideRight
|
||||||
|
visible: legend.width > 500
|
||||||
|
text: qsTr("Produced")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
onClicked: d.selectSeries(acquisitionSeries)
|
||||||
|
opacity: acquisitionSeries.opacity
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "power-grid"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.red
|
name: "power-grid"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.red
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "arrow-down"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.red
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "arrow-down"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.red
|
visible: legend.width > 500
|
||||||
|
text: qsTr("From grid")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
|
||||||
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
onClicked: d.selectSeries(returnSeries)
|
||||||
|
opacity: returnSeries.opacity
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "power-grid"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.yellow
|
name: "power-grid"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.yellow
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "arrow-up"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.yellow
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "arrow-up"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.yellow
|
visible: legend.width > 500
|
||||||
|
text: qsTr("To grid")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
|
||||||
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
visible: batteries.count > 0
|
visible: batteries.count > 0
|
||||||
|
onClicked: d.selectSeries(toStorageSeries)
|
||||||
|
opacity: toStorageSeries.opacity
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "battery/battery-080"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.purple
|
name: "battery/battery-080"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.purple
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "plus"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.purple
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "plus"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.purple
|
visible: legend.width > 500
|
||||||
|
text: qsTr("To battery")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
|
||||||
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
visible: batteries.count > 0
|
visible: batteries.count > 0
|
||||||
|
onClicked: d.selectSeries(fromStorageSeries)
|
||||||
|
opacity: fromStorageSeries.opacity
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "battery/battery-040"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.orange
|
name: "battery/battery-040"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.orange
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "minus"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.orange
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "minus"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.orange
|
visible: legend.width > 500
|
||||||
|
text: qsTr("From battery")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,6 +673,7 @@ Item {
|
|||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
preventStealing: tooltipping || dragging
|
preventStealing: tooltipping || dragging
|
||||||
|
propagateComposedEvents: true
|
||||||
|
|
||||||
property int startMouseX: 0
|
property int startMouseX: 0
|
||||||
property bool dragging: false
|
property bool dragging: false
|
||||||
|
|||||||
21
nymea-app/ui/mainviews/energy/PowerBalanceHistoryPage.qml
Normal file
21
nymea-app/ui/mainviews/energy/PowerBalanceHistoryPage.qml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("My power balance history")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerBalanceHistory {
|
||||||
|
id: powerBalanceHistory
|
||||||
|
anchors.fill: parent
|
||||||
|
titleVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,8 @@ StatsBase {
|
|||||||
|
|
||||||
property EnergyManager energyManager: null
|
property EnergyManager energyManager: null
|
||||||
|
|
||||||
|
property bool titleVisible: true
|
||||||
|
|
||||||
property ThingsProxy producers: ThingsProxy {
|
property ThingsProxy producers: ThingsProxy {
|
||||||
engine: _engine
|
engine: _engine
|
||||||
shownInterfaces: ["smartmeterproducer"]
|
shownInterfaces: ["smartmeterproducer"]
|
||||||
@ -22,6 +24,8 @@ StatsBase {
|
|||||||
property var config: root.configs[selectionTabs.currentValue.config]
|
property var config: root.configs[selectionTabs.currentValue.config]
|
||||||
property int startOffset: 0
|
property int startOffset: 0
|
||||||
|
|
||||||
|
property var selectedSet: null
|
||||||
|
|
||||||
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
|
property date startTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset)
|
||||||
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
|
property date endTime: root.calculateTimestamp(config.startTime(), config.sampleRate, startOffset + config.count)
|
||||||
|
|
||||||
@ -38,6 +42,14 @@ StatsBase {
|
|||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectSet(set) {
|
||||||
|
if (d.selectedSet === set) {
|
||||||
|
d.selectedSet = null
|
||||||
|
} else {
|
||||||
|
d.selectedSet = set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (powerBalanceLogs.loadingInhibited) {
|
if (powerBalanceLogs.loadingInhibited) {
|
||||||
return;
|
return;
|
||||||
@ -106,12 +118,17 @@ StatsBase {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
// Label {
|
Label {
|
||||||
// Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
// Layout.margins: Style.smallMargins
|
Layout.margins: Style.smallMargins
|
||||||
// horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// text: qsTr("Totals")
|
text: qsTr("Totals")
|
||||||
// }
|
visible: root.titleVisible
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("PowerBalanceStatsPage.qml"), {energyManager: root.energyManager, producers: root.producers})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SelectionTabs {
|
SelectionTabs {
|
||||||
id: selectionTabs
|
id: selectionTabs
|
||||||
@ -278,7 +295,7 @@ StatsBase {
|
|||||||
BarSet {
|
BarSet {
|
||||||
id: consumptionSet
|
id: consumptionSet
|
||||||
label: qsTr("Consumed")
|
label: qsTr("Consumed")
|
||||||
color: Style.blue
|
color: Qt.rgba(Style.blue.r, Style.blue.g, Style.blue.b, d.selectedSet == null || d.selectedSet == consumptionSet ? 1 : 0.3)
|
||||||
borderColor: color
|
borderColor: color
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
values: {
|
values: {
|
||||||
@ -292,7 +309,7 @@ StatsBase {
|
|||||||
BarSet {
|
BarSet {
|
||||||
id: productionSet
|
id: productionSet
|
||||||
label: qsTr("Produced")
|
label: qsTr("Produced")
|
||||||
color: Style.green
|
color: Qt.rgba(Style.green.r, Style.green.g, Style.green.b, d.selectedSet == null || d.selectedSet == productionSet ? 1 : 0.3)
|
||||||
borderColor: color
|
borderColor: color
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
values: {
|
values: {
|
||||||
@ -306,7 +323,7 @@ StatsBase {
|
|||||||
BarSet {
|
BarSet {
|
||||||
id: acquisitionSet
|
id: acquisitionSet
|
||||||
label: qsTr("From grid")
|
label: qsTr("From grid")
|
||||||
color: Style.red
|
color: Qt.rgba(Style.red.r, Style.red.g, Style.red.b, d.selectedSet == null || d.selectedSet == acquisitionSet ? 1 : 0.3)
|
||||||
borderColor: color
|
borderColor: color
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
values: {
|
values: {
|
||||||
@ -320,7 +337,7 @@ StatsBase {
|
|||||||
BarSet {
|
BarSet {
|
||||||
id: returnSet
|
id: returnSet
|
||||||
label: qsTr("To grid")
|
label: qsTr("To grid")
|
||||||
color: Style.yellow
|
color: Qt.rgba(Style.yellow.r, Style.yellow.g, Style.yellow.b, d.selectedSet == null || d.selectedSet == returnSet ? 1 : 0.3)
|
||||||
borderColor: color
|
borderColor: color
|
||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
values: {
|
values: {
|
||||||
@ -335,64 +352,113 @@ StatsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: legend
|
||||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
|
||||||
anchors.leftMargin: chartView.plotArea.x
|
anchors.leftMargin: chartView.plotArea.x
|
||||||
height: Style.smallIconSize
|
height: Style.smallIconSize
|
||||||
anchors.margins: Style.margins
|
anchors.margins: Style.margins
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
ColorIcon {
|
onClicked: d.selectSet(consumptionSet)
|
||||||
name: "powersocket"
|
Row {
|
||||||
size: Style.smallIconSize
|
|
||||||
color: Style.blue
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.smallMargins
|
||||||
|
ColorIcon {
|
||||||
|
name: "powersocket"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.blue
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
width: parent.parent.width - x
|
||||||
|
elide: Text.ElideRight
|
||||||
|
visible: legend.width > 500
|
||||||
|
text: qsTr("Consumed")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
ColorIcon {
|
onClicked: d.selectSet(productionSet)
|
||||||
name: "weathericons/weather-clear-day"
|
Row {
|
||||||
size: Style.smallIconSize
|
|
||||||
color: Style.green
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
spacing: Style.smallMargins
|
||||||
|
ColorIcon {
|
||||||
|
name: "weathericons/weather-clear-day"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.green
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
width: parent.parent.width - x
|
||||||
|
elide: Text.ElideRight
|
||||||
|
visible: legend.width > 500
|
||||||
|
text: qsTr("Produced")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
onClicked: d.selectSet(acquisitionSet)
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "power-grid"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.red
|
name: "power-grid"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.red
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "arrow-down"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.red
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "arrow-down"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.red
|
visible: legend.width > 500
|
||||||
|
text: qsTr("From grid")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
MouseArea {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
onClicked: d.selectSet(returnSet)
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
ColorIcon {
|
spacing: Style.smallMargins
|
||||||
name: "power-grid"
|
Row {
|
||||||
size: Style.smallIconSize
|
ColorIcon {
|
||||||
color: Style.yellow
|
name: "power-grid"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.yellow
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
name: "arrow-up"
|
||||||
|
size: Style.smallIconSize
|
||||||
|
color: Style.yellow
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColorIcon {
|
Label {
|
||||||
name: "arrow-up"
|
width: parent.parent.width - x
|
||||||
size: Style.smallIconSize
|
elide: Text.ElideRight
|
||||||
color: Style.yellow
|
visible: legend.width > 500
|
||||||
|
text: qsTr("To grid")
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font: Style.smallFont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,7 +630,7 @@ StatsBase {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
width: Style.extraSmallFont.pixelSize
|
width: Style.extraSmallFont.pixelSize
|
||||||
height: width
|
height: width
|
||||||
color: Style.yellow
|
color: Style.green
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: d.startOffset !== undefined ? qsTr("Produced: %1 kWh").arg(productionSet.at(toolTip.idx).toFixed(2)) : ""
|
text: d.startOffset !== undefined ? qsTr("Produced: %1 kWh").arg(productionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||||
@ -586,7 +652,7 @@ StatsBase {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
width: Style.extraSmallFont.pixelSize
|
width: Style.extraSmallFont.pixelSize
|
||||||
height: width
|
height: width
|
||||||
color: Style.green
|
color: Style.yellow
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: d.startOffset !== undefined ? qsTr("To grid: %1 kWh").arg(returnSet.at(toolTip.idx).toFixed(2)) : ""
|
text: d.startOffset !== undefined ? qsTr("To grid: %1 kWh").arg(returnSet.at(toolTip.idx).toFixed(2)) : ""
|
||||||
|
|||||||
24
nymea-app/ui/mainviews/energy/PowerBalanceStatsPage.qml
Normal file
24
nymea-app/ui/mainviews/energy/PowerBalanceStatsPage.qml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "qrc:/ui/components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property alias energyManager: powerBalanceStats
|
||||||
|
property alias producers: powerBalanceStats.producers
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Power balance totals")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerBalanceStats {
|
||||||
|
id: powerBalanceStats
|
||||||
|
anchors.fill: parent
|
||||||
|
titleVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -154,7 +154,7 @@ Item {
|
|||||||
property bool inhibitChartsAnimation: PlatformHelper.deviceModel.startsWith("SM-G950") // Samsung S8 has a buggy GPU driver :(
|
property bool inhibitChartsAnimation: PlatformHelper.deviceModel.startsWith("SM-G950") // Samsung S8 has a buggy GPU driver :(
|
||||||
property int chartsAnimationOptions: !inhibitChartsAnimation ? ChartView.SeriesAnimations : ChartView.NoAnimation
|
property int chartsAnimationOptions: !inhibitChartsAnimation ? ChartView.SeriesAnimations : ChartView.NoAnimation
|
||||||
|
|
||||||
function generateColor(baseColor, index) {
|
function generateColor(baseColor, index, alpha) {
|
||||||
var stepSize = 30
|
var stepSize = 30
|
||||||
var baseHSV = rgb2hsv(baseColor.r, baseColor.g, baseColor.b)
|
var baseHSV = rgb2hsv(baseColor.r, baseColor.g, baseColor.b)
|
||||||
var currentHue = baseHSV[0]
|
var currentHue = baseHSV[0]
|
||||||
@ -170,7 +170,7 @@ Item {
|
|||||||
}
|
}
|
||||||
handledColors.push(currentHue)
|
handledColors.push(currentHue)
|
||||||
}
|
}
|
||||||
return Qt.hsva(currentHue / 360, baseHSV[1], baseHSV[2], 1);
|
return Qt.hsva(currentHue / 360, baseHSV[1], baseHSV[2], alpha || 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function rgb2hsv(r,g,b) {
|
function rgb2hsv(r,g,b) {
|
||||||
|
|||||||
Reference in New Issue
Block a user