more work on qtcharts
This commit is contained in:
parent
37c4ed0261
commit
65d983d5e3
@ -213,9 +213,39 @@ void LogsModelNg::logsReply(const QVariantMap &data)
|
||||
for (int i = 0; i < newBlock.count(); i++) {
|
||||
LogEntry *entry = newBlock.at(i);
|
||||
m_list.insert(offset + i, entry);
|
||||
qDebug() << "Adding line series point:" << i << entry->timestamp().toSecsSinceEpoch() << entry->value().toReal();
|
||||
|
||||
if (m_graphSeries) {
|
||||
m_graphSeries->insert(offset + i, QPointF(entry->timestamp().toMSecsSinceEpoch(), entry->value().toReal()));
|
||||
Device *dev = m_engine->deviceManager()->devices()->getDevice(entry->deviceId());
|
||||
if (dev && dev->deviceClass()->stateTypes()->getStateType(entry->typeId())->type() == "Bool") {
|
||||
// We don't want bools painting triangles, add a toggle point to keep lines straight
|
||||
if (i > 0) {
|
||||
LogEntry *newerEntry = newBlock.at(i - 1);
|
||||
if (newerEntry->value().toBool() != entry->value().toBool()) {
|
||||
qDebug() << "Adding bool line series point:" << (newerEntry->timestamp().addSecs(-1)) << newerEntry->timestamp().addSecs(-1).toMSecsSinceEpoch() << (entry->value().toBool() ? 1 : 0) << "(correction)";
|
||||
m_graphSeries->append(QPointF(newerEntry->timestamp().addSecs(-1).toMSecsSinceEpoch(), entry->value().toBool() ? 1 : 0));
|
||||
}
|
||||
}
|
||||
if (m_graphSeries->count() == 0) {
|
||||
qDebug() << "Adding bool line series point:" << QDateTime::currentDateTime() << QDateTime::currentDateTime().toMSecsSinceEpoch() - 1 << (entry->value().toBool() ? 1 : 0) << "(beginning)";
|
||||
m_graphSeries->append(QPointF(QDateTime::currentDateTime().toMSecsSinceEpoch(), 1));// entry->value().toBool() ? 1 : 0));
|
||||
m_graphSeries->append(QPointF(QDateTime::currentDateTime().toMSecsSinceEpoch(), entry->value().toBool() ? 1 : 0));
|
||||
}
|
||||
qDebug() << "Adding bool line series point:" << entry->timestamp() << entry->timestamp().toMSecsSinceEpoch() << (entry->value().toBool() ? 1 : 0);
|
||||
m_graphSeries->append(QPointF(entry->timestamp().toMSecsSinceEpoch(), entry->value().toBool() ? 1 : 0));
|
||||
} else {
|
||||
// if (i > 0) {
|
||||
// LogEntry *newerEntry = newBlock.at(i - 1);
|
||||
// if (newerEntry->value() != entry->value()) {
|
||||
// qDebug() << "Adding line series point:" << (offset + i) << newerEntry->timestamp().toMSecsSinceEpoch() - 1 << (entry->value().toReal()) << "(correction)";
|
||||
// m_graphSeries->append(QPointF(newerEntry->timestamp().toMSecsSinceEpoch() - 1, entry->value().toReal()));
|
||||
// }
|
||||
// }
|
||||
if (m_graphSeries->count() == 0) {
|
||||
m_graphSeries->insert(0, QPointF(QDateTime::currentDateTime().toMSecsSinceEpoch(), entry->value().toReal()));
|
||||
}
|
||||
qDebug() << "Adding line series point:" << (offset + i) << entry->timestamp().toMSecsSinceEpoch() << (entry->value().toReal());
|
||||
m_graphSeries->append(QPointF(entry->timestamp().toMSecsSinceEpoch(), entry->value().toReal()));
|
||||
}
|
||||
}
|
||||
if (!newMin.isValid() || newMin > entry->value()) {
|
||||
newMin = entry->value().toReal();
|
||||
@ -236,7 +266,7 @@ void LogsModelNg::logsReply(const QVariantMap &data)
|
||||
emit maxValueChanged();
|
||||
}
|
||||
|
||||
if (m_list.count() > 0 && m_list.last()->timestamp() > m_viewStartTime && canFetchMore()) {
|
||||
if (m_viewStartTime.isValid() && m_list.count() > 0 && m_list.last()->timestamp() > m_viewStartTime && canFetchMore()) {
|
||||
fetchMore();
|
||||
}
|
||||
}
|
||||
@ -246,8 +276,8 @@ void LogsModelNg::fetchMore(const QModelIndex &parent)
|
||||
Q_UNUSED(parent)
|
||||
qDebug() << "fetchMore called";
|
||||
|
||||
if (!m_engine->jsonRpcClient()) {
|
||||
qWarning() << "Cannot update. JsonRpcClient not set";
|
||||
if (!m_engine) {
|
||||
qWarning() << "Cannot update. Engine not set";
|
||||
return;
|
||||
}
|
||||
if (m_busy) {
|
||||
@ -294,8 +324,8 @@ void LogsModelNg::fetchMore(const QModelIndex &parent)
|
||||
bool LogsModelNg::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
qDebug() << "canFetchMore" << m_canFetchMore;
|
||||
return m_canFetchMore;
|
||||
qDebug() << "canFetchMore" << (m_engine && m_canFetchMore);
|
||||
return m_engine && m_canFetchMore;
|
||||
}
|
||||
|
||||
void LogsModelNg::newLogEntryReceived(const QVariantMap &data)
|
||||
|
||||
@ -127,5 +127,7 @@
|
||||
<file>translations/nymea-app-de_DE.qm</file>
|
||||
<file>translations/nymea-app-en_US.qm</file>
|
||||
<file>../LICENSE</file>
|
||||
<file>ui/customviews/GenericTypeGraphPre110.qml</file>
|
||||
<file>ui/customviews/GenericTypeGraph.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
252
nymea-app/ui/customviews/GenericTypeGraph.qml
Normal file
252
nymea-app/ui/customviews/GenericTypeGraph.qml
Normal file
@ -0,0 +1,252 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
import "../customviews"
|
||||
import QtCharts 2.2
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var device: null
|
||||
property var stateType: null
|
||||
readonly property var deviceClass: engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
readonly property bool hasConnectable: deviceClass.interfaces.indexOf("connectable") >= 0
|
||||
readonly property var connectedStateType: hasConnectable ? deviceClass.stateTypes.findByName("connected") : null
|
||||
|
||||
LogsModelNg {
|
||||
id: logsModelNg
|
||||
engine: _engine
|
||||
deviceId: root.device.id
|
||||
typeIds: [root.stateType.id]
|
||||
live: true
|
||||
graphSeries: lineSeries1
|
||||
viewStartTime: xAxis.min
|
||||
}
|
||||
|
||||
LogsModelNg {
|
||||
id: connectedLogsModel
|
||||
engine: root.hasConnectable ? _engine : null // don't even try to poll if we don't have a connectable interface
|
||||
deviceId: root.device.id
|
||||
typeIds: [root.connectedStateType.id]
|
||||
live: true
|
||||
graphSeries: connectedLineSeries
|
||||
viewStartTime: xAxis.min
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
HeaderButton {
|
||||
imageSource: "../images/zoom-out.svg"
|
||||
onClicked: {
|
||||
var diff = xAxis.max.getTime() - xAxis.min.getTime()
|
||||
var newTime = new Date(xAxis.min.getTime() - (diff / 4))
|
||||
xAxis.min = newTime;
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.preferredWidth: 100
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: {
|
||||
var timeDiff = (xAxis.max.getTime() - xAxis.min.getTime()) / 1000;
|
||||
if (timeDiff < 60) {
|
||||
return qsTr("%1 seconds").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff = timeDiff / 60
|
||||
if (timeDiff < 60) {
|
||||
return qsTr("%1 minutes").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff = timeDiff / 60
|
||||
if (timeDiff < 48) {
|
||||
return qsTr("%1 hours").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff = timeDiff / 24;
|
||||
if (timeDiff < 14) {
|
||||
return qsTr("%1 days").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff = timeDiff / 7
|
||||
if (timeDiff < 5) {
|
||||
return qsTr("%1 weeks").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff * timeDiff * 7 / 30
|
||||
if (timeDiff < 24) {
|
||||
return qsTr("%1 months").arg(Math.round(timeDiff));
|
||||
}
|
||||
timeDiff = timeDiff * 30 / 356
|
||||
return qsTr("%1 years").arg(Math.round(timeDiff))
|
||||
}
|
||||
}
|
||||
|
||||
HeaderButton {
|
||||
imageSource: "../images/zoom-in.svg"
|
||||
onClicked: {
|
||||
var diff = xAxis.max.getTime() - xAxis.min.getTime()
|
||||
var newTime = new Date(xAxis.min.getTime() + (diff / 4))
|
||||
xAxis.min = newTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChartView {
|
||||
id: chartView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
margins.top: 0
|
||||
margins.bottom: 0
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
backgroundColor: Material.background
|
||||
legend.labelColor: app.foregroundColor
|
||||
|
||||
animationDuration: 300
|
||||
animationOptions: ChartView.SeriesAnimations
|
||||
|
||||
ValueAxis {
|
||||
id: yAxis
|
||||
min: logsModelNg.minValue
|
||||
max: logsModelNg.maxValue
|
||||
labelsFont.pixelSize: app.smallFont
|
||||
labelsColor: app.foregroundColor
|
||||
tickCount: chartView.height / 40
|
||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .2)
|
||||
gridLineColor: color
|
||||
}
|
||||
|
||||
ValueAxis {
|
||||
id: connectedAxis
|
||||
min: 0
|
||||
max: 1
|
||||
visible: false
|
||||
}
|
||||
|
||||
DateTimeAxis {
|
||||
id: xAxis
|
||||
gridVisible: false
|
||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .2)
|
||||
tickCount: chartView.width / 70
|
||||
labelsFont.pixelSize: app.smallFont
|
||||
labelsColor: app.foregroundColor
|
||||
titleText: {
|
||||
if (xAxis.min.getYear() === xAxis.max.getYear()
|
||||
&& xAxis.min.getMonth() === xAxis.max.getMonth()
|
||||
&& xAxis.min.getDate() === xAxis.max.getDate()) {
|
||||
return Qt.formatDate(xAxis.min)
|
||||
}
|
||||
return Qt.formatDate(xAxis.min) + " - " + Qt.formatDate(xAxis.max)
|
||||
}
|
||||
titleBrush: app.foregroundColor
|
||||
format: {
|
||||
var timeDiff = (xAxis.max.getTime() - xAxis.min.getTime()) / 1000
|
||||
if (timeDiff < 60) { // one minute
|
||||
return "mm:ss"
|
||||
}
|
||||
if (timeDiff < 60 * 60) { // one hour
|
||||
return "hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 2) { // two day
|
||||
return "hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 7) { // one week
|
||||
return "ddd hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 7 * 30) { // one month
|
||||
return "dd.MM."
|
||||
}
|
||||
return "MMM yy"
|
||||
}
|
||||
|
||||
min: {
|
||||
var date = new Date();
|
||||
date.setHours(date.getHours() - 6);
|
||||
return date;
|
||||
}
|
||||
max: new Date()
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
axisX: xAxis
|
||||
axisY: connectedAxis
|
||||
name: qsTr("Not connected")
|
||||
visible: root.hasConnectable
|
||||
upperSeries: LineSeries {
|
||||
XYPoint {x: xAxis.min.getTime(); y: 1}
|
||||
XYPoint {x: xAxis.max.getTime(); y: 1}
|
||||
}
|
||||
|
||||
lowerSeries: LineSeries {
|
||||
id: connectedLineSeries
|
||||
}
|
||||
color: "#55ff0000"
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
axisX: xAxis
|
||||
axisY: yAxis
|
||||
name: root.stateType.displayName
|
||||
borderColor: app.accentColor
|
||||
borderWidth: 4
|
||||
upperSeries: LineSeries {
|
||||
id: lineSeries1
|
||||
}
|
||||
color: Qt.rgba(app.accentColor.r, app.accentColor.g, app.accentColor.b, .3)
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property int lastX: 0
|
||||
property int lastY: 0
|
||||
|
||||
function scrollRightLimited(dx) {
|
||||
chartView.animationOptions = ChartView.NoAnimation
|
||||
var now = new Date()
|
||||
// if we're already at the limit, don't even start scrolling
|
||||
if (dx < 0 || xAxis.max < now) {
|
||||
chartView.scrollRight(dx)
|
||||
}
|
||||
// figure out if we scrolled too far
|
||||
var overshoot = xAxis.max.getTime() - now.getTime()
|
||||
// print("overshoot is:", overshoot, "oldMax", xAxis.max, "newMax", now, "oldMin", xAxis.min, "newMin", new Date(xAxis.min.getTime() - overshoot))
|
||||
if (overshoot > 0) {
|
||||
var range = xAxis.max - xAxis.min
|
||||
xAxis.max = now
|
||||
xAxis.min = new Date(xAxis.max.getTime() - range)
|
||||
}
|
||||
chartView.animationOptions = ChartView.SeriesAnimations
|
||||
}
|
||||
|
||||
function zoomInLimited(dy) {
|
||||
chartView.animationOptions = ChartView.NoAnimation
|
||||
var oldMax = xAxis.max;
|
||||
chartView.scrollRight(dy);
|
||||
var timeDiff = xAxis.max.getTime() - oldMax.getTime()
|
||||
xAxis.min = new Date(xAxis.min.getTime() - timeDiff * 2)
|
||||
chartView.animationOptions = ChartView.SeriesAnimations
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
lastX = mouse.x
|
||||
lastY = mouse.y
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
scrollRightLimited(-wheel.pixelDelta.x)
|
||||
// zoomInLimited(wheel.pixelDelta.y)
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
if (lastX !== mouse.x) {
|
||||
scrollRightLimited(lastX - mouseX)
|
||||
lastX = mouse.x
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
84
nymea-app/ui/customviews/GenericTypeGraphPre110.qml
Normal file
84
nymea-app/ui/customviews/GenericTypeGraphPre110.qml
Normal file
@ -0,0 +1,84 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
import "../customviews"
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property var device: null
|
||||
property var stateType: null
|
||||
|
||||
TabBar {
|
||||
id: zoomTabBar
|
||||
Layout.fillWidth: true
|
||||
TabButton {
|
||||
text: qsTr("6 h")
|
||||
property int avg: ValueLogsProxyModel.AverageQuarterHour
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setHours(new Date().getHours() - 6)
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("24 h")
|
||||
property int avg: ValueLogsProxyModel.AverageHourly
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setHours(new Date().getHours() - 24);
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("7 d")
|
||||
property int avg: ValueLogsProxyModel.AverageDayTime
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setDate(new Date().getDate() - 7);
|
||||
date.setHours(0)
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Graph {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
mode: settings.graphStyle
|
||||
color: app.accentColor
|
||||
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: 10
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
graphModel.update()
|
||||
}
|
||||
}
|
||||
|
||||
model: ValueLogsProxyModel {
|
||||
id: graphModel
|
||||
deviceId: root.device.id
|
||||
typeIds: [stateType.id]
|
||||
average: zoomTabBar.currentItem.avg
|
||||
startTime: zoomTabBar.currentItem.startTime
|
||||
Component.onCompleted: updateTimer.start();
|
||||
onAverageChanged: updateTimer.start()
|
||||
onStartTimeChanged: updateTimer.start();
|
||||
engine: _engine
|
||||
|
||||
// Live doesn't work yet with ValueLogsProxyModel
|
||||
// live: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
import "../customviews"
|
||||
import QtCharts 2.2
|
||||
|
||||
Page {
|
||||
id: root
|
||||
@ -24,7 +23,7 @@ Page {
|
||||
}
|
||||
|
||||
header: GuhHeader {
|
||||
text: qsTr("History")
|
||||
text: qsTr("History for %1").arg(root.stateType.displayName)
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
@ -45,8 +44,6 @@ Page {
|
||||
deviceId: root.device.id
|
||||
typeIds: [root.stateType.id]
|
||||
live: true
|
||||
graphSeries: lineSeries1
|
||||
viewStartTime: xAxis.min
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@ -62,9 +59,6 @@ Page {
|
||||
TabButton {
|
||||
text: qsTr("Graph")
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("Graph NG")
|
||||
}
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
@ -96,225 +90,19 @@ Page {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Loader {
|
||||
id: graphLoader
|
||||
width: swipeView.width
|
||||
height: swipeView.height
|
||||
TabBar {
|
||||
id: zoomTabBar
|
||||
Layout.fillWidth: true
|
||||
TabButton {
|
||||
text: qsTr("6 h")
|
||||
property int avg: ValueLogsProxyModel.AverageQuarterHour
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setHours(new Date().getHours() - 6)
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("24 h")
|
||||
property int avg: ValueLogsProxyModel.AverageHourly
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setHours(new Date().getHours() - 24);
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("7 d")
|
||||
property int avg: ValueLogsProxyModel.AverageDayTime
|
||||
property date startTime: {
|
||||
var date = new Date();
|
||||
date.setDate(new Date().getDate() - 7);
|
||||
date.setHours(0)
|
||||
date.setMinutes(0)
|
||||
date.setSeconds(0)
|
||||
return date;
|
||||
}
|
||||
Component.onCompleted: {
|
||||
var source;
|
||||
if (engine.jsonRpcClient.ensureServerVersion("1.10")) {
|
||||
source = Qt.resolvedUrl("../customviews/GenericTypeGraph.qml");
|
||||
} else {
|
||||
source = Qt.resolvedUrl("../customviews/GenericTypeGraphPre110.qml");
|
||||
}
|
||||
setSource(source, {device: root.device, stateType: root.stateType})
|
||||
}
|
||||
|
||||
Graph {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
mode: settings.graphStyle
|
||||
color: app.accentColor
|
||||
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: 10
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
graphModel.update()
|
||||
}
|
||||
}
|
||||
|
||||
model: ValueLogsProxyModel {
|
||||
id: graphModel
|
||||
deviceId: root.device.id
|
||||
typeIds: [stateType.id]
|
||||
average: zoomTabBar.currentItem.avg
|
||||
startTime: zoomTabBar.currentItem.startTime
|
||||
Component.onCompleted: updateTimer.start();
|
||||
onAverageChanged: updateTimer.start()
|
||||
onStartTimeChanged: updateTimer.start();
|
||||
engine: _engine
|
||||
|
||||
// Live doesn't work yet with ValueLogsProxyModel
|
||||
// live: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
width: swipeView.width
|
||||
height: swipeView.height
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
HeaderButton {
|
||||
imageSource: "../images/zoom-in.svg"
|
||||
onClicked: {
|
||||
var diff = xAxis.max.getTime() - xAxis.min.getTime()
|
||||
var newTime = new Date(xAxis.min.getTime() + (diff / 4))
|
||||
xAxis.min = newTime;
|
||||
}
|
||||
}
|
||||
HeaderButton {
|
||||
imageSource: "../images/zoom-out.svg"
|
||||
onClicked: {
|
||||
var diff = xAxis.max.getTime() - xAxis.min.getTime()
|
||||
var newTime = new Date(xAxis.min.getTime() - (diff / 4))
|
||||
xAxis.min = newTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChartView {
|
||||
id: chartView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
margins.top: 0
|
||||
margins.bottom: 0
|
||||
margins.left: 0
|
||||
margins.right: 0
|
||||
backgroundColor: Material.background
|
||||
animationDuration: 300
|
||||
animationOptions: ChartView.SeriesAnimations
|
||||
|
||||
ValueAxis {
|
||||
id: yAxis
|
||||
min: logsModelNg.minValue
|
||||
max: logsModelNg.maxValue
|
||||
labelsFont.pixelSize: app.smallFont
|
||||
tickCount: chartView.height / 40
|
||||
}
|
||||
|
||||
DateTimeAxis {
|
||||
id: xAxis
|
||||
gridVisible: false
|
||||
tickCount: chartView.width / 70
|
||||
labelsFont.pixelSize: app.smallFont
|
||||
format: {
|
||||
var timeDiff = (xAxis.max.getTime() - xAxis.min.getTime()) / 1000
|
||||
if (timeDiff < 60) { // one minute
|
||||
return "mm:ss"
|
||||
}
|
||||
if (timeDiff < 60 * 60) { // one hour
|
||||
return "hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 2) { // two day
|
||||
return "hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 7) { // one week
|
||||
return "ddd hh:mm"
|
||||
}
|
||||
if (timeDiff < 60 * 60 * 24 * 7 * 30) { // one month
|
||||
return "dd.MM."
|
||||
}
|
||||
return "MMM yy"
|
||||
}
|
||||
|
||||
min: {
|
||||
var date = new Date();
|
||||
date.setHours(date.getHours() - 6);
|
||||
return date;
|
||||
}
|
||||
max: new Date()
|
||||
}
|
||||
|
||||
AreaSeries {
|
||||
axisX: xAxis
|
||||
axisY: yAxis
|
||||
name: root.stateType.displayName
|
||||
borderColor: app.accentColor
|
||||
borderWidth: 4
|
||||
upperSeries: LineSeries {
|
||||
id: lineSeries1
|
||||
width: 4
|
||||
}
|
||||
color: Qt.rgba(app.accentColor.r, app.accentColor.g, app.accentColor.b, .3)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property int lastX: 0
|
||||
property int lastY: 0
|
||||
|
||||
function scrollRightLimited(dx) {
|
||||
chartView.animationOptions = ChartView.NoAnimation
|
||||
var now = new Date()
|
||||
// if we're already at the limit, don't even start scrolling
|
||||
if (dx < 0 || xAxis.max < now) {
|
||||
chartView.scrollRight(dx)
|
||||
}
|
||||
// figure out if we scrolled too far
|
||||
var overshoot = xAxis.max.getTime() - now.getTime()
|
||||
print("overshoot is:", overshoot, "oldMax", xAxis.max, "newMax", now, "oldMin", xAxis.min, "newMin", new Date(xAxis.min.getTime() - overshoot))
|
||||
if (overshoot > 0) {
|
||||
var range = xAxis.max - xAxis.min
|
||||
xAxis.max = now
|
||||
xAxis.min = new Date(xAxis.max.getTime() - range)
|
||||
}
|
||||
chartView.animationOptions = ChartView.SeriesAnimations
|
||||
}
|
||||
|
||||
function zoomInLimited(dy) {
|
||||
chartView.animationOptions = ChartView.NoAnimation
|
||||
var oldMax = xAxis.max;
|
||||
chartView.scrollRight(dy);
|
||||
var timeDiff = xAxis.max.getTime() - oldMax.getTime()
|
||||
xAxis.min = new Date(xAxis.min.getTime() - timeDiff * 2)
|
||||
chartView.animationOptions = ChartView.SeriesAnimations
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
lastX = mouse.x
|
||||
lastY = mouse.y
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
scrollRightLimited(-wheel.pixelDelta.x)
|
||||
// zoomInLimited(wheel.pixelDelta.y)
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
if (lastX !== mouse.x) {
|
||||
scrollRightLimited(lastX - mouseX)
|
||||
lastX = mouse.x
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user