Merge PR #730: Blur chart tooltips
This commit is contained in:
commit
e2e61b6637
@ -272,5 +272,6 @@
|
||||
<file>ui/mainviews/energy/StatsBase.qml</file>
|
||||
<file>ui/mainviews/energy/EnergySettingsPage.qml</file>
|
||||
<file>ui/mainviews/energy/ConsumersPieChart.qml</file>
|
||||
<file>ui/components/NymeaToolTip.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -239,13 +239,17 @@ Page {
|
||||
id: contentContainer
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
// visible: false
|
||||
|
||||
property int headerSize: 48
|
||||
|
||||
readonly property int scrollOffset: swipeView.currentItem.item.contentY
|
||||
readonly property int headerBlurSize: Math.min(headerSize, scrollOffset * 2)
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: contentContainer.headerBlurSize
|
||||
color: Style.backgroundColor
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
id: swipeView
|
||||
|
||||
@ -13,6 +13,8 @@ Item {
|
||||
property color tileOverlayForegroundColor: foregroundColor
|
||||
property color tileOverlayIconColor: iconColor
|
||||
|
||||
property color tooltipBackgroundColor: tileOverlayColor
|
||||
|
||||
property int cornerRadius: 6
|
||||
property int smallCornerRadius: 4
|
||||
|
||||
|
||||
43
nymea-app/ui/components/NymeaToolTip.qml
Normal file
43
nymea-app/ui/components/NymeaToolTip.qml
Normal file
@ -0,0 +1,43 @@
|
||||
import QtQuick 2.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import Nymea 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias backgroundItem: blurEffectSource.sourceItem
|
||||
property alias backgroundRect: blurEffectSource.sourceRect
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
|
||||
Rectangle {
|
||||
id: blurSource
|
||||
anchors.fill: toolTip
|
||||
color: Style.backgroundColor
|
||||
visible: false
|
||||
radius: Style.smallCornerRadius
|
||||
|
||||
ShaderEffectSource {
|
||||
id: blurEffectSource
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
anchors.fill: toolTip
|
||||
source: blurSource
|
||||
radius: 32
|
||||
visible: toolTip.visible
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tooltipBackgroundColor
|
||||
opacity: .5
|
||||
radius: Style.smallCornerRadius
|
||||
}
|
||||
|
||||
}
|
||||
@ -361,81 +361,72 @@ StatsBase {
|
||||
|
||||
property var thingBarSetMap: ({})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: chartView.x + chartView.plotArea.x
|
||||
anchors.topMargin: chartView.y + chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: chartView
|
||||
anchors.leftMargin: chartView.plotArea.x
|
||||
anchors.topMargin: chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
hoverEnabled: true
|
||||
|
||||
hoverEnabled: true
|
||||
Timer {
|
||||
interval: 300
|
||||
running: mouseArea.pressed
|
||||
onTriggered: mouseArea.preventStealing = true
|
||||
}
|
||||
onReleased: mouseArea.preventStealing = false
|
||||
|
||||
Timer {
|
||||
interval: 300
|
||||
running: mouseArea.pressed
|
||||
onTriggered: mouseArea.preventStealing = true
|
||||
NymeaToolTip {
|
||||
id: toolTip
|
||||
|
||||
backgroundItem: chartView
|
||||
backgroundRect: Qt.rect(chartView.plotArea.x + toolTip.x, chartView.plotArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||
|
||||
property int idx: Math.floor(mouseArea.mouseX * categoryAxis.count / mouseArea.width)
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
x: Math.min(idx * mouseArea.width / categoryAxis.count, mouseArea.width - width)
|
||||
property double setMaxValue: {
|
||||
var max = 0;
|
||||
for (var i = 0; i < consumers.count; i++) {
|
||||
var consumer = consumers.get(i)
|
||||
max = barSeries.thingBarSetMap.hasOwnProperty(consumer.id) ? Math.max(max, barSeries.thingBarSetMap[consumer.id].at(idx)) : 0
|
||||
}
|
||||
onReleased: mouseArea.preventStealing = false
|
||||
return max
|
||||
}
|
||||
y: Math.min(Math.max(mouseArea.height - (setMaxValue * mouseArea.height / valueAxis.max) - height - Style.smallMargins, 0), mouseArea.height - height)
|
||||
|
||||
Item {
|
||||
id: toolTip
|
||||
property int idx: Math.floor(mouseArea.mouseX * categoryAxis.count / mouseArea.width)
|
||||
visible: mouseArea.containsMouse
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
x: Math.min(idx * mouseArea.width / categoryAxis.count, mouseArea.width - width)
|
||||
property double setMaxValue: {
|
||||
var max = 0;
|
||||
for (var i = 0; i < consumers.count; i++) {
|
||||
var consumer = consumers.get(i)
|
||||
max = barSeries.thingBarSetMap.hasOwnProperty(consumer.id) ? Math.max(max, barSeries.thingBarSetMap[consumer.id].at(idx)) : 0
|
||||
}
|
||||
return max
|
||||
}
|
||||
y: Math.min(Math.max(mouseArea.height - (setMaxValue * mouseArea.height / valueAxis.max) - height - Style.smallMargins, 0), mouseArea.height - height)
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
margins: Style.smallMargins
|
||||
}
|
||||
Label {
|
||||
text: toolTip.idx >= 0 && categoryAxis.timestamps.length > toolTip.idx ? root.configs[selectionTabs.currentValue.config].toLongLabel(categoryAxis.timestamps[toolTip.idx]) : ""
|
||||
font: Style.smallFont
|
||||
}
|
||||
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tileOverlayColor
|
||||
opacity: .8
|
||||
radius: Style.smallCornerRadius
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
margins: Style.smallMargins
|
||||
Repeater {
|
||||
model: consumers
|
||||
delegate: RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: index >= 0 ? root.colors[index % root.colors.length] : "white"
|
||||
}
|
||||
Label {
|
||||
text: toolTip.idx >= 0 && categoryAxis.timestamps.length > toolTip.idx ? root.configs[selectionTabs.currentValue.config].toLongLabel(categoryAxis.timestamps[toolTip.idx]) : ""
|
||||
font: Style.smallFont
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: consumers
|
||||
delegate: RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: index >= 0 ? root.colors[index % root.colors.length] : "white"
|
||||
}
|
||||
Label {
|
||||
text: barSeries.thingBarSetMap.hasOwnProperty(model.id) ? "%1: %2 kWh".arg(model.name).arg(barSeries.thingBarSetMap[model.id].at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
text: barSeries.thingBarSetMap.hasOwnProperty(model.id) ? "%1: %2 kWh".arg(model.name).arg(barSeries.thingBarSetMap[model.id].at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,24 +3,12 @@ import QtCharts 2.3
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.3
|
||||
import Nymea 1.0
|
||||
import "qrc:/ui/components"
|
||||
|
||||
ChartView {
|
||||
Item {
|
||||
id: root
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
property var colors: null
|
||||
|
||||
title: qsTr("Consumers history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
property ThingsProxy consumers: null
|
||||
|
||||
Connections {
|
||||
@ -119,7 +107,7 @@ ChartView {
|
||||
thingPowerLogs.loadingInhibited = true;
|
||||
|
||||
for (var thingId in d.thingsSeriesMap) {
|
||||
root.removeSeries(d.thingsSeriesMap[thingId])
|
||||
chartView.removeSeries(d.thingsSeriesMap[thingId])
|
||||
}
|
||||
d.thingsSeriesMap = ({})
|
||||
|
||||
@ -130,17 +118,17 @@ ChartView {
|
||||
var baseSeries = zeroSeries;
|
||||
if (i > 0) {
|
||||
baseSeries = d.thingsSeriesMap[consumerThingIds[i-1]].upperSeries
|
||||
// print("base for:", thing.name, "is", engine.thingManager.things.getThing(consumerThingIds[i-1]).name)
|
||||
// print("base for:", thing.name, "is", engine.thingManager.things.getThing(consumerThingIds[i-1]).name)
|
||||
}
|
||||
|
||||
var series = root.createSeries(ChartView.SeriesTypeArea, thing.name, dateTimeAxis, valueAxis)
|
||||
var series = chartView.createSeries(ChartView.SeriesTypeArea, thing.name, dateTimeAxis, valueAxis)
|
||||
series.lowerSeries = baseSeries
|
||||
series.upperSeries = lineSeriesComponent.createObject(series)
|
||||
series.color = root.colors[i % root.colors.length]
|
||||
series.borderWidth = 0;
|
||||
series.borderColor = series.color
|
||||
|
||||
// print("Adding thingId series", thing.id, thing.name)
|
||||
// print("Adding thingId series", thing.id, thing.name)
|
||||
var map = d.thingsSeriesMap
|
||||
map[thing.id] = series
|
||||
d.thingsSeriesMap = map
|
||||
@ -156,95 +144,116 @@ ChartView {
|
||||
LineSeries { }
|
||||
}
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(powerBalanceLogs.maxValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
// visible: false
|
||||
ChartView {
|
||||
id: chartView
|
||||
anchors.fill: parent
|
||||
|
||||
}
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: root.plotArea.y
|
||||
height: root.plotArea.height
|
||||
width: plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
|
||||
title: qsTr("Consumers history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(powerBalanceLogs.maxValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
// visible: false
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: chartView.plotArea.y
|
||||
height: chartView.plotArea.height
|
||||
width: chartView.plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
id: consumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.gray
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Unknown")
|
||||
AreaSeries {
|
||||
id: consumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.gray
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Unknown")
|
||||
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
}
|
||||
}
|
||||
upperSeries: LineSeries {
|
||||
id: consumptionUpperSeries
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
consumptionUpperSeries.append(entry.timestamp.getTime(), entry.consumption)
|
||||
}
|
||||
}
|
||||
upperSeries: LineSeries {
|
||||
id: consumptionUpperSeries
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
consumptionUpperSeries.append(entry.timestamp.getTime(), entry.consumption)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: root.plotArea.x
|
||||
anchors.topMargin: root.plotArea.y
|
||||
anchors.rightMargin: root.width - root.plotArea.width - root.plotArea.x
|
||||
anchors.bottomMargin: root.height - root.plotArea.height - root.plotArea.y
|
||||
anchors.leftMargin: chartView.plotArea.x
|
||||
anchors.topMargin: chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
@ -263,10 +272,13 @@ ChartView {
|
||||
visible: mouseArea.containsMouse
|
||||
}
|
||||
|
||||
Item {
|
||||
NymeaToolTip {
|
||||
id: toolTip
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
backgroundItem: chartView
|
||||
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||
|
||||
property int idx: consumptionUpperSeries.count - Math.floor(mouseArea.mouseX * consumptionUpperSeries.count / mouseArea.width)
|
||||
property int seriesIndex: consumptionUpperSeries.count - idx
|
||||
|
||||
@ -281,18 +293,6 @@ ChartView {
|
||||
|
||||
property date timestamp: new Date(consumptionUpperSeries.at(seriesIndex).x)
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tileOverlayColor
|
||||
opacity: .8
|
||||
radius: Style.smallCornerRadius
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
|
||||
@ -316,107 +316,98 @@ StatsBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: chartView
|
||||
anchors.leftMargin: chartView.plotArea.x
|
||||
anchors.topMargin: chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: chartView.x + chartView.plotArea.x
|
||||
anchors.topMargin: chartView.y + chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
|
||||
hoverEnabled: true
|
||||
hoverEnabled: true
|
||||
|
||||
Timer {
|
||||
interval: 300
|
||||
running: mouseArea.pressed
|
||||
onTriggered: mouseArea.preventStealing = true
|
||||
Timer {
|
||||
interval: 300
|
||||
running: mouseArea.pressed
|
||||
onTriggered: mouseArea.preventStealing = true
|
||||
}
|
||||
onReleased: mouseArea.preventStealing = false
|
||||
|
||||
NymeaToolTip {
|
||||
id: toolTip
|
||||
|
||||
backgroundItem: chartView
|
||||
backgroundRect: Qt.rect(chartView.plotArea.x + toolTip.x, chartView.plotArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||
|
||||
property int idx: Math.floor(mouseArea.mouseX * categoryAxis.count / mouseArea.width)
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
x: Math.min(idx * mouseArea.width / categoryAxis.count, mouseArea.width - width)
|
||||
property double setMaxValue: d.consumptionSet && d.productionSet && d.acquisitionSet && d.returnSet ?
|
||||
Math.max(d.consumptionSet.at(idx), Math.max(d.productionSet.at(idx), Math.max(d.acquisitionSet.at(idx), d.returnSet.at(idx))))
|
||||
: 0
|
||||
y: Math.min(Math.max(mouseArea.height - (setMaxValue * mouseArea.height / valueAxis.max) - height - Style.smallMargins, 0), mouseArea.height - height)
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
margins: Style.smallMargins
|
||||
}
|
||||
onReleased: mouseArea.preventStealing = false
|
||||
|
||||
Item {
|
||||
id: toolTip
|
||||
property int idx: Math.floor(mouseArea.mouseX * categoryAxis.count / mouseArea.width)
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
x: Math.min(idx * mouseArea.width / categoryAxis.count, mouseArea.width - width)
|
||||
property double setMaxValue: d.consumptionSet && d.productionSet && d.acquisitionSet && d.returnSet ?
|
||||
Math.max(d.consumptionSet.at(idx), Math.max(d.productionSet.at(idx), Math.max(d.acquisitionSet.at(idx), d.returnSet.at(idx))))
|
||||
: 0
|
||||
y: Math.min(Math.max(mouseArea.height - (setMaxValue * mouseArea.height / valueAxis.max) - height - Style.smallMargins, 0), mouseArea.height - height)
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
Label {
|
||||
text: toolTip.idx >= 0 && categoryAxis.timestamps.length > toolTip.idx ? root.configs[selectionTabs.currentValue.config].toLongLabel(categoryAxis.timestamps[toolTip.idx]) : ""
|
||||
font: Style.smallFont
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tileOverlayColor
|
||||
opacity: .8
|
||||
radius: Style.smallCornerRadius
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.blue
|
||||
}
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
margins: Style.smallMargins
|
||||
}
|
||||
|
||||
Label {
|
||||
text: toolTip.idx >= 0 && categoryAxis.timestamps.length > toolTip.idx ? root.configs[selectionTabs.currentValue.config].toLongLabel(categoryAxis.timestamps[toolTip.idx]) : ""
|
||||
font: Style.smallFont
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.blue
|
||||
}
|
||||
Label {
|
||||
text: d.consumptionSet ? qsTr("Consumed: %1 kWh").arg(d.consumptionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.green
|
||||
}
|
||||
Label {
|
||||
text: d.productionSet ? qsTr("Produced: %1 kWh").arg(d.productionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.red
|
||||
}
|
||||
Label {
|
||||
text: d.acquisitionSet ? qsTr("From grid: %1 kWh").arg(d.acquisitionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.orange
|
||||
}
|
||||
Label {
|
||||
text: d.returnSet ? qsTr("To grid: %1 kWh").arg(d.returnSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
Label {
|
||||
text: d.consumptionSet ? qsTr("Consumed: %1 kWh").arg(d.consumptionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.green
|
||||
}
|
||||
Label {
|
||||
text: d.productionSet ? qsTr("Produced: %1 kWh").arg(d.productionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.red
|
||||
}
|
||||
Label {
|
||||
text: d.acquisitionSet ? qsTr("From grid: %1 kWh").arg(d.acquisitionSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Style.extraSmallFont.pixelSize
|
||||
height: width
|
||||
color: Style.orange
|
||||
}
|
||||
Label {
|
||||
text: d.returnSet ? qsTr("To grid: %1 kWh").arg(d.returnSet.at(toolTip.idx).toFixed(2)) : ""
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,22 +2,12 @@ import QtQuick 2.0
|
||||
import QtCharts 2.3
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import Nymea 1.0
|
||||
import "qrc:/ui/components"
|
||||
|
||||
ChartView {
|
||||
Item {
|
||||
id: root
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
title: qsTr("My consumption history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
property PowerBalanceLogs energyLogs: PowerBalanceLogs {
|
||||
id: powerBalanceLogs
|
||||
@ -63,179 +53,198 @@ ChartView {
|
||||
}
|
||||
}
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(powerBalanceLogs.maxValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
// visible: false
|
||||
ChartView {
|
||||
id: chartView
|
||||
anchors.fill: parent
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
}
|
||||
title: qsTr("My consumption history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: root.plotArea.y
|
||||
height: root.plotArea.height
|
||||
width: plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(powerBalanceLogs.maxValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
// visible: false
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: chartView.plotArea.y
|
||||
height: chartView.plotArea.height
|
||||
width: chartView.plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
|
||||
// For debugging, to see the total graph and check if the other maths line up
|
||||
AreaSeries {
|
||||
id: consumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: "blue"
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
opacity: .5
|
||||
visible: false
|
||||
|
||||
lowerSeries: zeroSeries
|
||||
upperSeries: LineSeries {
|
||||
id: consumptionUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return entry.consumption
|
||||
}
|
||||
function addEntry(entry) {
|
||||
consumptionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
AreaSeries {
|
||||
id: selfProductionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.green
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Self production")
|
||||
// visible: false
|
||||
|
||||
// For debugging, to see the total graph and check if the other maths line up
|
||||
AreaSeries {
|
||||
id: consumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: "blue"
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
opacity: .5
|
||||
visible: false
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
}
|
||||
}
|
||||
|
||||
lowerSeries: zeroSeries
|
||||
upperSeries: LineSeries {
|
||||
id: consumptionUpperSeries
|
||||
}
|
||||
upperSeries: LineSeries {
|
||||
id: selfProductionUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return entry.consumption
|
||||
}
|
||||
function addEntry(entry) {
|
||||
consumptionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
function calculateValue(entry) {
|
||||
var value = entry.consumption - Math.max(0, entry.acquisition);
|
||||
if (entry.storage < 0) {
|
||||
value += entry.storage;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
AreaSeries {
|
||||
id: selfProductionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.green
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Self production")
|
||||
// visible: false
|
||||
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
function addEntry(entry) {
|
||||
selfProductionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
|
||||
upperSeries: LineSeries {
|
||||
id: selfProductionUpperSeries
|
||||
}
|
||||
AreaSeries {
|
||||
id: storageSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.orange
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("From battery")
|
||||
// visible: false
|
||||
|
||||
function calculateValue(entry) {
|
||||
var value = entry.consumption - Math.max(0, entry.acquisition);
|
||||
if (entry.storage < 0) {
|
||||
value += entry.storage;
|
||||
lowerSeries: selfProductionUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: storageUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return selfProductionSeries.calculateValue(entry) + Math.abs(Math.min(0, entry.storage));
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
storageUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
selfProductionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
|
||||
AreaSeries {
|
||||
id: acquisitionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.red
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("From grid")
|
||||
// visible: false
|
||||
|
||||
lowerSeries: storageUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: acquisitionUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return storageSeries.calculateValue(entry) + Math.max(0, entry.acquisition)
|
||||
}
|
||||
function addEntry(entry) {
|
||||
acquisitionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
id: storageSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.orange
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("From battery")
|
||||
// visible: false
|
||||
|
||||
lowerSeries: selfProductionUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: storageUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return selfProductionSeries.calculateValue(entry) + Math.abs(Math.min(0, entry.storage));
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
storageUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AreaSeries {
|
||||
id: acquisitionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.red
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("From grid")
|
||||
// visible: false
|
||||
|
||||
lowerSeries: storageUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: acquisitionUpperSeries
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return storageSeries.calculateValue(entry) + Math.max(0, entry.acquisition)
|
||||
}
|
||||
function addEntry(entry) {
|
||||
acquisitionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: root.plotArea.x
|
||||
anchors.topMargin: root.plotArea.y
|
||||
anchors.rightMargin: root.width - root.plotArea.width - root.plotArea.x
|
||||
anchors.bottomMargin: root.height - root.plotArea.height - root.plotArea.y
|
||||
anchors.fill: chartView
|
||||
anchors.leftMargin: chartView.plotArea.x
|
||||
anchors.topMargin: chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
@ -254,10 +263,15 @@ ChartView {
|
||||
visible: mouseArea.containsMouse
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
NymeaToolTip {
|
||||
id: toolTip
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
backgroundItem: chartView
|
||||
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||
|
||||
|
||||
property int idx: consumptionUpperSeries.count - (Math.floor(mouseArea.mouseX * consumptionUpperSeries.count / mouseArea.width))
|
||||
property int seriesIndex: consumptionUpperSeries.count - idx
|
||||
|
||||
@ -270,18 +284,6 @@ ChartView {
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tileOverlayColor
|
||||
opacity: .8
|
||||
radius: Style.smallCornerRadius
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
@ -334,3 +336,4 @@ ChartView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,21 +3,10 @@ import QtCharts 2.3
|
||||
import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.3
|
||||
import Nymea 1.0
|
||||
import "qrc:/ui/components"
|
||||
|
||||
ChartView {
|
||||
Item {
|
||||
id: root
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
title: qsTr("My production history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
property PowerBalanceLogs energyLogs: PowerBalanceLogs {
|
||||
id: powerBalanceLogs
|
||||
@ -62,173 +51,192 @@ ChartView {
|
||||
}
|
||||
}
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(-powerBalanceLogs.minValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
}
|
||||
ChartView {
|
||||
id: chartView
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: root.plotArea.y
|
||||
height: root.plotArea.height
|
||||
width: plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
}
|
||||
backgroundColor: "transparent"
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
margins.bottom: 0
|
||||
margins.top: 0
|
||||
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
title: qsTr("My production history")
|
||||
titleColor: Style.foregroundColor
|
||||
|
||||
// For debugging, to see if the other maths line up with the plain production graph
|
||||
AreaSeries {
|
||||
id: productionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: "blue"
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
opacity: .5
|
||||
name: "Total production"
|
||||
visible: false
|
||||
legend.alignment: Qt.AlignBottom
|
||||
legend.labelColor: Style.foregroundColor
|
||||
legend.font: Style.extraSmallFont
|
||||
|
||||
function calculateValue(entry) {
|
||||
return Math.abs(Math.min(0, entry.production))
|
||||
}
|
||||
function addEntry(entry) {
|
||||
productionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
|
||||
ValueAxis {
|
||||
id: valueAxis
|
||||
min: 0
|
||||
max: Math.ceil(-powerBalanceLogs.minValue / 1000) * 1000
|
||||
labelFormat: ""
|
||||
gridLineColor: Style.tileOverlayColor
|
||||
labelsVisible: false
|
||||
lineVisible: false
|
||||
titleVisible: false
|
||||
shadesVisible: false
|
||||
}
|
||||
|
||||
lowerSeries: zeroSeries
|
||||
upperSeries: LineSeries {
|
||||
id: productionUpperSeries
|
||||
}
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
id: selfConsumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.red
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Consumed")
|
||||
// visible: false
|
||||
|
||||
function calculateValue(entry) {
|
||||
return Math.abs(Math.min(0, entry.production)) - Math.abs(Math.min(0, entry.acquisition)) - Math.max(0, entry.storage)
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
selfConsumptionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
Item {
|
||||
id: labelsLayout
|
||||
x: Style.smallMargins
|
||||
y: chartView.plotArea.y
|
||||
height: chartView.plotArea.height
|
||||
width: chartView.plotArea.x - x
|
||||
Repeater {
|
||||
model: valueAxis.tickCount
|
||||
delegate: Label {
|
||||
y: parent.height / (valueAxis.tickCount - 1) * index - font.pixelSize / 2
|
||||
width: parent.width - Style.smallMargins
|
||||
horizontalAlignment: Text.AlignRight
|
||||
text: ((valueAxis.max - (index * valueAxis.max / (valueAxis.tickCount - 1))) / 1000).toFixed(2) + "kW"
|
||||
verticalAlignment: Text.AlignTop
|
||||
font: Style.extraSmallFont
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upperSeries: LineSeries {
|
||||
id: selfConsumptionUpperSeries
|
||||
}
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
id: storageSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.orange
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
// visible: false
|
||||
name: qsTr("To battery")
|
||||
|
||||
|
||||
function calculateValue(entry) {
|
||||
return selfConsumptionSeries.calculateValue(entry) + Math.abs(Math.max(0, entry.storage));
|
||||
DateTimeAxis {
|
||||
id: dateTimeAxis
|
||||
property date now: new Date()
|
||||
min: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() - (1000 * 60 * 60 * 24) + 2000);
|
||||
return date;
|
||||
}
|
||||
max: {
|
||||
var date = new Date(now);
|
||||
date.setTime(date.getTime() + 2000)
|
||||
return date;
|
||||
}
|
||||
format: "hh:mm"
|
||||
labelsFont: Style.extraSmallFont
|
||||
gridVisible: false
|
||||
minorGridVisible: false
|
||||
lineVisible: false
|
||||
shadesVisible: false
|
||||
labelsColor: Style.foregroundColor
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
storageUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
// For debugging, to see if the other maths line up with the plain production graph
|
||||
AreaSeries {
|
||||
id: productionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: "blue"
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
opacity: .5
|
||||
name: "Total production"
|
||||
visible: false
|
||||
|
||||
function calculateValue(entry) {
|
||||
return Math.abs(Math.min(0, entry.production))
|
||||
}
|
||||
function addEntry(entry) {
|
||||
productionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
|
||||
lowerSeries: zeroSeries
|
||||
upperSeries: LineSeries {
|
||||
id: productionUpperSeries
|
||||
}
|
||||
}
|
||||
|
||||
lowerSeries: selfConsumptionUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: storageUpperSeries
|
||||
}
|
||||
}
|
||||
AreaSeries {
|
||||
id: selfConsumptionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.red
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("Consumed")
|
||||
// visible: false
|
||||
|
||||
function calculateValue(entry) {
|
||||
return Math.abs(Math.min(0, entry.production)) - Math.abs(Math.min(0, entry.acquisition)) - Math.max(0, entry.storage)
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
id: acquisitionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.green
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("To grid")
|
||||
// visible: false
|
||||
function addEntry(entry) {
|
||||
selfConsumptionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
|
||||
function calculateValue(entry) {
|
||||
return storageSeries.calculateValue(entry) + Math.abs(Math.min(0, entry.acquisition))
|
||||
}
|
||||
function addEntry(entry) {
|
||||
acquisitionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
lowerSeries: LineSeries {
|
||||
id: zeroSeries
|
||||
XYPoint { x: dateTimeAxis.min.getTime(); y: 0 }
|
||||
XYPoint { x: dateTimeAxis.max.getTime(); y: 0 }
|
||||
function update(timestamp) {
|
||||
append(timestamp, 0);
|
||||
removePoints(1,1);
|
||||
}
|
||||
}
|
||||
|
||||
upperSeries: LineSeries {
|
||||
id: selfConsumptionUpperSeries
|
||||
}
|
||||
}
|
||||
|
||||
lowerSeries: storageUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: acquisitionUpperSeries
|
||||
AreaSeries {
|
||||
id: storageSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.orange
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
// visible: false
|
||||
name: qsTr("To battery")
|
||||
|
||||
|
||||
function calculateValue(entry) {
|
||||
return selfConsumptionSeries.calculateValue(entry) + Math.abs(Math.max(0, entry.storage));
|
||||
}
|
||||
|
||||
function addEntry(entry) {
|
||||
storageUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
|
||||
lowerSeries: selfConsumptionUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: storageUpperSeries
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AreaSeries {
|
||||
id: acquisitionSeries
|
||||
axisX: dateTimeAxis
|
||||
axisY: valueAxis
|
||||
color: Style.green
|
||||
borderWidth: 0
|
||||
borderColor: color
|
||||
name: qsTr("To grid")
|
||||
// visible: false
|
||||
|
||||
function calculateValue(entry) {
|
||||
return storageSeries.calculateValue(entry) + Math.abs(Math.min(0, entry.acquisition))
|
||||
}
|
||||
function addEntry(entry) {
|
||||
acquisitionUpperSeries.append(entry.timestamp.getTime(), calculateValue(entry))
|
||||
}
|
||||
|
||||
lowerSeries: storageUpperSeries
|
||||
upperSeries: LineSeries {
|
||||
id: acquisitionUpperSeries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: root.plotArea.x
|
||||
anchors.topMargin: root.plotArea.y
|
||||
anchors.rightMargin: root.width - root.plotArea.width - root.plotArea.x
|
||||
anchors.bottomMargin: root.height - root.plotArea.height - root.plotArea.y
|
||||
anchors.leftMargin: chartView.plotArea.x
|
||||
anchors.topMargin: chartView.plotArea.y
|
||||
anchors.rightMargin: chartView.width - chartView.plotArea.width - chartView.plotArea.x
|
||||
anchors.bottomMargin: chartView.height - chartView.plotArea.height - chartView.plotArea.y
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
@ -247,10 +255,13 @@ ChartView {
|
||||
visible: mouseArea.containsMouse
|
||||
}
|
||||
|
||||
Item {
|
||||
NymeaToolTip {
|
||||
id: toolTip
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
backgroundItem: chartView
|
||||
backgroundRect: Qt.rect(mouseArea.x + toolTip.x, mouseArea.y + toolTip.y, toolTip.width, toolTip.height)
|
||||
|
||||
property int idx: productionUpperSeries.count - Math.floor(mouseArea.mouseX * productionUpperSeries.count / mouseArea.width)
|
||||
property int seriesIndex: productionUpperSeries.count - idx
|
||||
|
||||
@ -263,18 +274,6 @@ ChartView {
|
||||
width: tooltipLayout.implicitWidth + Style.smallMargins * 2
|
||||
height: tooltipLayout.implicitHeight + Style.smallMargins * 2
|
||||
|
||||
Behavior on x { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on y { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on width { NumberAnimation { duration: Style.animationDuration } }
|
||||
Behavior on height { NumberAnimation { duration: Style.animationDuration } }
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.tileOverlayColor
|
||||
opacity: .8
|
||||
radius: Style.smallCornerRadius
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipLayout
|
||||
anchors {
|
||||
@ -327,3 +326,6 @@ ChartView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user