From a4275a238f2a913923ee5b09edecba9c89ee4df1 Mon Sep 17 00:00:00 2001 From: dodoradio Date: Wed, 19 Jul 2023 14:12:49 +0100 Subject: Rewrite the labelling system The label code has been split into its own set of components: -TimeLabels: These try to display time labels as best as possible. They can label intervals from a minute to a day, but the code for labelling weeks is still missing. There's also no code protecting against strings overlapping with each other. - VerticalLabels: The code for these is a bit more 'analogue' than that of the time labels, but it's roughly analogous to previous code. These have also been implemented for the heartrate graph. --- src/graphs/TimeLabels.qml | 149 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/graphs/TimeLabels.qml (limited to 'src/graphs/TimeLabels.qml') diff --git a/src/graphs/TimeLabels.qml b/src/graphs/TimeLabels.qml new file mode 100644 index 0000000..bebeca5 --- /dev/null +++ b/src/graphs/TimeLabels.qml @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2023 Arseniy Movshev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.15 +import org.asteroid.controls 1.0 + +Item { + id: root + property real startTime: 0 + property real endTime: 0 + property int minLabels: 3 //these min and max numbers of labels are only guidelines for the algorithm, and don't actually set hard limits. + property int maxLabels: 8 + property int startValueDivision + onStartTimeChanged: update() + onEndTimeChanged: update() + onMinLabelsChanged: update() + onMaxLabelsChanged: update() + Component.onCompleted: update() + function update() { + listModel.clear() + var delta = endTime - startTime + var interval = 0 + if (delta < 60 * maxLabels) { // check 1 minute + if (delta < 60 * minLabels) { + interval = 30 //label every 30s otherwise + } else { + interval = 60 + } + startValueDivision = interval * Math.ceil(startTime / interval) + // iterate and populate the list + var currentTime = startValueDivision + var i = 0; + var date + while (currentTime < endTime) { + date = new Date(currentTime*1000) + var value = date.getHours().toString() + ":" + date.getMinutes().toString() + var x = (currentTime - startTime) / delta + listModel.append({"value": value, "x": x}) + currentTime = currentTime + interval + i++ + } + + } else if (delta < 600 * maxLabels) { // check 10 minutes + if (delta < 600 * minLabels) { + interval = 300 //label every 5m otherwise + } else { + interval = 600 + } + startValueDivision = interval * Math.ceil(startTime / interval) + // iterate and populate the list + var currentTime = startValueDivision + var i = 0; + var date + while (currentTime < endTime) { + date = new Date(currentTime*1000) + var value = date.getHours().toString() + ":" + date.getMinutes().toString() + var x = (currentTime - startTime) / delta + listModel.append({"value": value, "x": x}) + currentTime = currentTime + interval + i++ + } + + } else if (delta < 7200 * maxLabels) { // check every 2 hours + if (delta > 3600 * maxLabels) { + interval = 7200 //label every 2h if 1h doesn't work - this is an ugly workaround so that a full day still gets some sort of divisions + } else if (delta < 3600 * minLabels) { + interval = 1800 //label every 30m otherwise + } else { + interval = 3600 + } + startValueDivision = interval * Math.ceil(startTime / interval) + // iterate and populate the list + var currentTime = startValueDivision + var i = 0; + var date + while (currentTime < endTime) { + date = new Date(currentTime*1000) + var value = date.getHours().toString() + ":" + date.getMinutes().toString() + var x = (currentTime - startTime) / delta + listModel.append({"value": value, "x": x}) + currentTime = currentTime + interval + i++ + } + + } else if (delta < 86400 * maxLabels) { // check days + if (delta < 86400 * minLabels) { + interval = 43200 //label every 12h otherwise + } else { + interval = 86400 + } + startValueDivision = interval * Math.ceil(startTime / interval) + // iterate and populate the list + var currentTime = startValueDivision + var i = 0; + var date + while (currentTime < endTime) { + date = new Date(currentTime*1000) + var value = date.getDate().toString() /* we should add am and pm here for 12h mode*/ + var x = ((currentTime - startTime) / delta) + listModel.append({"value": value, "x": x}) + currentTime = currentTime + interval + i++ + } + + } else if (delta < 604800 * maxLabels) { // check weeks + interval = 604800 + startValueDivision = interval * Math.ceil(startTime / interval) + // iterate and populate the list + var currentTime = startValueDivision + var i = 0; + var date + while (currentTime < endTime) { + date = new Date(currentTime*1000) + var value = date.getDate().toString() + var x = ((currentTime - startTime) / delta) + listModel.append({"value": value, "x": x}) + currentTime = currentTime + interval + i++ + } + } else { // handle months + console.log("viewing more than several days of data isn't implemented yet. please pester dodoradio about this.") + } + // this is slightly crude - we assume that the min and max label numbers will be set in such a way that halving gets us a reasonable interval. + // we also ignore everything over a number of weeks, as this needs a bit more thought that I don't want to deal with right now. this graph code is stalling too much other development. + } + Repeater { + model: ListModel { id: listModel } + delegate: Label { + text: model.value + font.pixelSize: Dims.w(5) + x: model.x*root.width - width/2 + verticalAlignment: Text.AlignVCenter + } + } +} -- cgit v1.2.3-54-g00ecf