2021-06-05 16:42:56 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include "profilescene.h"
|
2021-06-28 18:29:46 +00:00
|
|
|
#include "divecartesianaxis.h"
|
|
|
|
#include "core/pref.h"
|
|
|
|
#include "qt-models/diveplotdatamodel.h"
|
2021-06-05 16:42:56 +00:00
|
|
|
|
2021-06-28 18:29:46 +00:00
|
|
|
const static struct ProfileItemPos {
|
|
|
|
struct Pos {
|
|
|
|
QPointF on;
|
|
|
|
QPointF off;
|
|
|
|
};
|
|
|
|
struct Axis : public Pos {
|
|
|
|
QLineF shrinked;
|
|
|
|
QLineF expanded;
|
|
|
|
QLineF intermediate;
|
|
|
|
};
|
|
|
|
Axis depth;
|
|
|
|
Axis partialPressure;
|
|
|
|
Axis partialPressureTissue;
|
|
|
|
Axis partialPressureWithTankBar;
|
|
|
|
Axis percentage;
|
|
|
|
Axis percentageWithTankBar;
|
|
|
|
Axis time;
|
|
|
|
Axis cylinder;
|
|
|
|
Axis temperature;
|
|
|
|
Axis temperatureAll;
|
|
|
|
Axis heartBeat;
|
|
|
|
Axis heartBeatWithTankBar;
|
|
|
|
ProfileItemPos();
|
|
|
|
} itemPos;
|
|
|
|
|
|
|
|
ProfileScene::ProfileScene(double fontPrintScale) :
|
2021-07-29 04:50:59 +00:00
|
|
|
fontPrintScale(fontPrintScale),
|
|
|
|
printMode(false),
|
|
|
|
isGrayscale(false),
|
2021-06-28 18:29:46 +00:00
|
|
|
dataModel(new DivePlotDataModel(this)),
|
|
|
|
profileYAxis(new DepthAxis(fontPrintScale, *this)),
|
|
|
|
gasYAxis(new PartialGasPressureAxis(*dataModel, fontPrintScale, *this)),
|
|
|
|
temperatureAxis(new TemperatureAxis(fontPrintScale, *this)),
|
|
|
|
timeAxis(new TimeAxis(fontPrintScale, *this)),
|
|
|
|
cylinderPressureAxis(new DiveCartesianAxis(fontPrintScale, *this)),
|
|
|
|
heartBeatAxis(new DiveCartesianAxis(fontPrintScale, *this)),
|
|
|
|
percentageAxis(new DiveCartesianAxis(fontPrintScale, *this))
|
2021-06-05 16:42:56 +00:00
|
|
|
{
|
2021-06-05 16:49:00 +00:00
|
|
|
setSceneRect(0, 0, 100, 100);
|
|
|
|
setItemIndexMethod(QGraphicsScene::NoIndex);
|
2021-06-28 18:29:46 +00:00
|
|
|
|
|
|
|
// Initialize axes. Perhaps part of this should be moved down to the axes code?
|
|
|
|
profileYAxis->setOrientation(DiveCartesianAxis::TopToBottom);
|
|
|
|
profileYAxis->setMinimum(0);
|
|
|
|
profileYAxis->setTickInterval(M_OR_FT(10, 30));
|
|
|
|
profileYAxis->setTickSize(0.5);
|
|
|
|
profileYAxis->setLineSize(96);
|
|
|
|
|
|
|
|
timeAxis->setLineSize(92);
|
|
|
|
timeAxis->setTickSize(-0.5);
|
|
|
|
|
|
|
|
gasYAxis->setOrientation(DiveCartesianAxis::BottomToTop);
|
|
|
|
gasYAxis->setTickInterval(1);
|
|
|
|
gasYAxis->setTickSize(1);
|
|
|
|
gasYAxis->setMinimum(0);
|
|
|
|
gasYAxis->setFontLabelScale(0.7);
|
|
|
|
gasYAxis->setLineSize(96);
|
|
|
|
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
heartBeatAxis->setOrientation(DiveCartesianAxis::BottomToTop);
|
|
|
|
heartBeatAxis->setTickSize(0.2);
|
|
|
|
heartBeatAxis->setTickInterval(10);
|
|
|
|
heartBeatAxis->setFontLabelScale(0.7);
|
|
|
|
heartBeatAxis->setLineSize(96);
|
|
|
|
|
|
|
|
percentageAxis->setOrientation(DiveCartesianAxis::BottomToTop);
|
|
|
|
percentageAxis->setTickSize(0.2);
|
|
|
|
percentageAxis->setTickInterval(10);
|
|
|
|
percentageAxis->setFontLabelScale(0.7);
|
|
|
|
percentageAxis->setLineSize(96);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
temperatureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
|
|
|
|
temperatureAxis->setTickSize(2);
|
|
|
|
temperatureAxis->setTickInterval(300);
|
|
|
|
|
|
|
|
cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
|
|
|
|
cylinderPressureAxis->setTickSize(2);
|
|
|
|
cylinderPressureAxis->setTickInterval(30000);
|
|
|
|
|
|
|
|
heartBeatAxis->setTextVisible(true);
|
|
|
|
heartBeatAxis->setLinesVisible(true);
|
|
|
|
percentageAxis->setTextVisible(true);
|
|
|
|
percentageAxis->setLinesVisible(true);
|
|
|
|
|
|
|
|
temperatureAxis->setTextVisible(false);
|
|
|
|
temperatureAxis->setLinesVisible(false);
|
|
|
|
cylinderPressureAxis->setTextVisible(false);
|
|
|
|
cylinderPressureAxis->setLinesVisible(false);
|
|
|
|
timeAxis->setLinesVisible(true);
|
|
|
|
profileYAxis->setLinesVisible(true);
|
|
|
|
gasYAxis->setZValue(timeAxis->zValue() + 1);
|
|
|
|
|
|
|
|
// Add items to scene
|
|
|
|
addItem(profileYAxis);
|
|
|
|
addItem(gasYAxis);
|
|
|
|
addItem(temperatureAxis);
|
|
|
|
addItem(timeAxis);
|
|
|
|
addItem(cylinderPressureAxis);
|
|
|
|
addItem(percentageAxis);
|
|
|
|
addItem(heartBeatAxis);
|
2021-06-05 16:42:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ProfileScene::~ProfileScene()
|
|
|
|
{
|
|
|
|
}
|
2021-06-28 18:29:46 +00:00
|
|
|
|
|
|
|
static bool ppGraphsEnabled()
|
|
|
|
{
|
|
|
|
return prefs.pp_graphs.po2 || prefs.pp_graphs.pn2 || prefs.pp_graphs.phe;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProfileScene::updateAxes()
|
|
|
|
{
|
|
|
|
profileYAxis->setPos(itemPos.depth.on);
|
|
|
|
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
gasYAxis->update(); // Initialize ticks of partial pressure graph
|
|
|
|
if ((prefs.percentagegraph||prefs.hrgraph) && ppGraphsEnabled()) {
|
|
|
|
profileYAxis->animateChangeLine(itemPos.depth.shrinked);
|
|
|
|
temperatureAxis->setPos(itemPos.temperatureAll.on);
|
|
|
|
temperatureAxis->animateChangeLine(itemPos.temperature.shrinked);
|
|
|
|
cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked);
|
|
|
|
|
|
|
|
if (prefs.tankbar) {
|
|
|
|
percentageAxis->setPos(itemPos.percentageWithTankBar.on);
|
|
|
|
percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded);
|
|
|
|
heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.on);
|
|
|
|
heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded);
|
|
|
|
} else {
|
|
|
|
percentageAxis->setPos(itemPos.percentage.on);
|
|
|
|
percentageAxis->animateChangeLine(itemPos.percentage.expanded);
|
|
|
|
heartBeatAxis->setPos(itemPos.heartBeat.on);
|
|
|
|
heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded);
|
|
|
|
}
|
|
|
|
gasYAxis->setPos(itemPos.partialPressureTissue.on);
|
|
|
|
gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded);
|
|
|
|
} else if (ppGraphsEnabled() || prefs.hrgraph || prefs.percentagegraph) {
|
|
|
|
profileYAxis->animateChangeLine(itemPos.depth.intermediate);
|
|
|
|
temperatureAxis->setPos(itemPos.temperature.on);
|
|
|
|
temperatureAxis->animateChangeLine(itemPos.temperature.intermediate);
|
|
|
|
cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate);
|
|
|
|
if (prefs.tankbar) {
|
|
|
|
percentageAxis->setPos(itemPos.percentageWithTankBar.on);
|
|
|
|
percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded);
|
|
|
|
gasYAxis->setPos(itemPos.partialPressureWithTankBar.on);
|
|
|
|
gasYAxis->animateChangeLine(itemPos.partialPressureWithTankBar.expanded);
|
|
|
|
heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.on);
|
|
|
|
heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded);
|
|
|
|
} else {
|
|
|
|
gasYAxis->setPos(itemPos.partialPressure.on);
|
|
|
|
gasYAxis->animateChangeLine(itemPos.partialPressure.expanded);
|
|
|
|
percentageAxis->setPos(itemPos.percentage.on);
|
|
|
|
percentageAxis->animateChangeLine(itemPos.percentage.expanded);
|
|
|
|
heartBeatAxis->setPos(itemPos.heartBeat.on);
|
|
|
|
heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
profileYAxis->animateChangeLine(itemPos.depth.expanded);
|
|
|
|
if (prefs.tankbar) {
|
|
|
|
temperatureAxis->setPos(itemPos.temperatureAll.on);
|
|
|
|
} else {
|
|
|
|
temperatureAxis->setPos(itemPos.temperature.on);
|
|
|
|
}
|
|
|
|
temperatureAxis->animateChangeLine(itemPos.temperature.expanded);
|
|
|
|
cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded);
|
|
|
|
}
|
|
|
|
|
|
|
|
timeAxis->setPos(itemPos.time.on);
|
|
|
|
timeAxis->setLine(itemPos.time.expanded);
|
|
|
|
|
|
|
|
cylinderPressureAxis->setPos(itemPos.cylinder.on);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ProfileScene::isPointOutOfBoundaries(const QPointF &point) const
|
|
|
|
{
|
|
|
|
double xpos = timeAxis->valueAt(point);
|
|
|
|
double ypos = profileYAxis->valueAt(point);
|
|
|
|
return xpos > timeAxis->maximum() ||
|
|
|
|
xpos < timeAxis->minimum() ||
|
|
|
|
ypos > profileYAxis->maximum() ||
|
|
|
|
ypos < profileYAxis->minimum();
|
|
|
|
}
|
|
|
|
|
|
|
|
ProfileItemPos::ProfileItemPos()
|
|
|
|
{
|
|
|
|
// Scene is *always* (double) 100 / 100.
|
|
|
|
// TODO: The relative scaling doesn't work well with large or small
|
|
|
|
// profiles and needs to be fixed.
|
|
|
|
|
|
|
|
//Depth Axis Config
|
|
|
|
depth.on.setX(3);
|
|
|
|
depth.on.setY(3);
|
|
|
|
depth.off.setX(-2);
|
|
|
|
depth.off.setY(3);
|
|
|
|
depth.expanded.setP1(QPointF(0, 0));
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
depth.expanded.setP2(QPointF(0, 85));
|
|
|
|
#else
|
|
|
|
depth.expanded.setP2(QPointF(0, 65));
|
|
|
|
#endif
|
|
|
|
depth.shrinked.setP1(QPointF(0, 0));
|
|
|
|
depth.shrinked.setP2(QPointF(0, 55));
|
|
|
|
depth.intermediate.setP1(QPointF(0, 0));
|
|
|
|
depth.intermediate.setP2(QPointF(0, 65));
|
|
|
|
|
|
|
|
// Time Axis Config
|
|
|
|
time.on.setX(3);
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
time.on.setY(95);
|
|
|
|
#else
|
|
|
|
time.on.setY(89.5);
|
|
|
|
#endif
|
|
|
|
time.off.setX(3);
|
|
|
|
time.off.setY(110);
|
|
|
|
time.expanded.setP1(QPointF(0, 0));
|
|
|
|
time.expanded.setP2(QPointF(94, 0));
|
|
|
|
|
|
|
|
// Partial Gas Axis Config
|
|
|
|
partialPressure.on.setX(97);
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
partialPressure.on.setY(75);
|
|
|
|
#else
|
|
|
|
partialPressure.on.setY(70);
|
|
|
|
#endif
|
|
|
|
partialPressure.off.setX(110);
|
|
|
|
partialPressure.off.setY(63);
|
|
|
|
partialPressure.expanded.setP1(QPointF(0, 0));
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
partialPressure.expanded.setP2(QPointF(0, 19));
|
|
|
|
#else
|
|
|
|
partialPressure.expanded.setP2(QPointF(0, 20));
|
|
|
|
#endif
|
|
|
|
partialPressureWithTankBar = partialPressure;
|
|
|
|
partialPressureWithTankBar.expanded.setP2(QPointF(0, 17));
|
|
|
|
partialPressureTissue = partialPressure;
|
|
|
|
partialPressureTissue.on.setX(97);
|
|
|
|
partialPressureTissue.on.setY(65);
|
|
|
|
partialPressureTissue.expanded.setP2(QPointF(0, 16));
|
|
|
|
|
|
|
|
// cylinder axis config
|
|
|
|
cylinder.on.setX(3);
|
|
|
|
cylinder.on.setY(20);
|
|
|
|
cylinder.off.setX(-10);
|
|
|
|
cylinder.off.setY(20);
|
|
|
|
cylinder.expanded.setP1(QPointF(0, 15));
|
|
|
|
cylinder.expanded.setP2(QPointF(0, 50));
|
|
|
|
cylinder.shrinked.setP1(QPointF(0, 0));
|
|
|
|
cylinder.shrinked.setP2(QPointF(0, 20));
|
|
|
|
cylinder.intermediate.setP1(QPointF(0, 0));
|
|
|
|
cylinder.intermediate.setP2(QPointF(0, 20));
|
|
|
|
|
|
|
|
// Temperature axis config
|
|
|
|
temperature.on.setX(3);
|
|
|
|
temperature.off.setX(-10);
|
|
|
|
temperature.off.setY(40);
|
|
|
|
temperature.expanded.setP1(QPointF(0, 20));
|
|
|
|
temperature.expanded.setP2(QPointF(0, 33));
|
|
|
|
temperature.shrinked.setP1(QPointF(0, 2));
|
|
|
|
temperature.shrinked.setP2(QPointF(0, 12));
|
|
|
|
#ifndef SUBSURFACE_MOBILE
|
|
|
|
temperature.on.setY(60);
|
|
|
|
temperatureAll.on.setY(51);
|
|
|
|
temperature.intermediate.setP1(QPointF(0, 2));
|
|
|
|
temperature.intermediate.setP2(QPointF(0, 12));
|
|
|
|
#else
|
|
|
|
temperature.on.setY(51);
|
|
|
|
temperatureAll.on.setY(47);
|
|
|
|
temperature.intermediate.setP1(QPointF(0, 2));
|
|
|
|
temperature.intermediate.setP2(QPointF(0, 12));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Heart rate axis config
|
|
|
|
heartBeat.on.setX(3);
|
|
|
|
heartBeat.on.setY(82);
|
|
|
|
heartBeat.expanded.setP1(QPointF(0, 0));
|
|
|
|
heartBeat.expanded.setP2(QPointF(0, 10));
|
|
|
|
heartBeatWithTankBar = heartBeat;
|
|
|
|
heartBeatWithTankBar.expanded.setP2(QPointF(0, 7));
|
|
|
|
|
|
|
|
// Percentage axis config
|
|
|
|
percentage.on.setX(3);
|
|
|
|
percentage.on.setY(80);
|
|
|
|
percentage.expanded.setP1(QPointF(0, 0));
|
|
|
|
percentage.expanded.setP2(QPointF(0, 15));
|
|
|
|
percentageWithTankBar = percentage;
|
|
|
|
percentageWithTankBar.expanded.setP2(QPointF(0, 11.9));
|
|
|
|
}
|